1 // Copyright (C) 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <aidl/android/os/StatsDimensionsValueParcel.h>
16 #include <android-base/properties.h>
17 #include <android-base/stringprintf.h>
18 #include <android/binder_interface_utils.h>
19 #include <gtest/gtest.h>
20
21 #include <thread>
22
23 #include "flags/flags.h"
24 #include "src/StatsLogProcessor.h"
25 #include "src/StatsService.h"
26 #include "src/storage/StorageManager.h"
27 #include "src/subscriber/SubscriberReporter.h"
28 #include "tests/statsd_test_util.h"
29
30 namespace android {
31 namespace os {
32 namespace statsd {
33
34 #ifdef __ANDROID__
35
36 using aidl::android::os::StatsDimensionsValueParcel;
37 using android::base::SetProperty;
38 using android::base::StringPrintf;
39 using ::ndk::SharedRefBase;
40 using namespace std;
41
42 // Tests that only run with the partial config update feature turned on.
43 namespace {
44 // Setup for test fixture.
45 class ConfigUpdateE2eTest : public ::testing::Test {
46 };
47
ValidateSubsystemSleepDimension(const DimensionsValue & value,string name)48 void ValidateSubsystemSleepDimension(const DimensionsValue& value, string name) {
49 EXPECT_EQ(value.field(), util::SUBSYSTEM_SLEEP_STATE);
50 ASSERT_EQ(value.value_tuple().dimensions_value_size(), 1);
51 EXPECT_EQ(value.value_tuple().dimensions_value(0).field(), 1 /* subsystem name field */);
52 EXPECT_EQ(value.value_tuple().dimensions_value(0).value_str(), name);
53 }
54
55 } // Anonymous namespace.
56
TEST_F(ConfigUpdateE2eTest,TestEventMetric)57 TEST_F(ConfigUpdateE2eTest, TestEventMetric) {
58 StatsdConfig config;
59 config.add_allowed_log_source("AID_ROOT");
60
61 AtomMatcher syncStartMatcher = CreateSyncStartAtomMatcher();
62 *config.add_atom_matcher() = syncStartMatcher;
63 AtomMatcher wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
64 *config.add_atom_matcher() = wakelockAcquireMatcher;
65 AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
66 *config.add_atom_matcher() = screenOnMatcher;
67 AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
68 *config.add_atom_matcher() = screenOffMatcher;
69 AtomMatcher batteryPluggedUsbMatcher = CreateBatteryStateUsbMatcher();
70 *config.add_atom_matcher() = batteryPluggedUsbMatcher;
71 AtomMatcher unpluggedMatcher = CreateBatteryStateNoneMatcher();
72 *config.add_atom_matcher() = unpluggedMatcher;
73
74 AtomMatcher* combinationMatcher = config.add_atom_matcher();
75 combinationMatcher->set_id(StringToId("SyncOrWakelockMatcher"));
76 combinationMatcher->mutable_combination()->set_operation(LogicalOperation::OR);
77 addMatcherToMatcherCombination(syncStartMatcher, combinationMatcher);
78 addMatcherToMatcherCombination(wakelockAcquireMatcher, combinationMatcher);
79
80 Predicate screenOnPredicate = CreateScreenIsOnPredicate();
81 *config.add_predicate() = screenOnPredicate;
82 Predicate unpluggedPredicate = CreateDeviceUnpluggedPredicate();
83 *config.add_predicate() = unpluggedPredicate;
84
85 Predicate* combinationPredicate = config.add_predicate();
86 combinationPredicate->set_id(StringToId("ScreenOnOrUnpluggedPred)"));
87 combinationPredicate->mutable_combination()->set_operation(LogicalOperation::OR);
88 addPredicateToPredicateCombination(screenOnPredicate, combinationPredicate);
89 addPredicateToPredicateCombination(unpluggedPredicate, combinationPredicate);
90
91 EventMetric eventPersist =
92 createEventMetric("SyncOrWlWhileScreenOnOrUnplugged", combinationMatcher->id(),
93 combinationPredicate->id());
94 EventMetric eventChange = createEventMetric(
95 "WakelockWhileScreenOn", wakelockAcquireMatcher.id(), screenOnPredicate.id());
96 EventMetric eventRemove = createEventMetric("Syncs", syncStartMatcher.id(), nullopt);
97
98 *config.add_event_metric() = eventRemove;
99 *config.add_event_metric() = eventPersist;
100 *config.add_event_metric() = eventChange;
101
102 ConfigKey key(123, 987);
103 uint64_t bucketStartTimeNs = 10000000000; // 0:10
104 sp<StatsLogProcessor> processor =
105 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, key);
106
107 int app1Uid = 123;
108 vector<int> attributionUids1 = {app1Uid};
109 vector<string> attributionTags1 = {"App1"};
110
111 // Initialize log events before update.
112 std::vector<std::unique_ptr<LogEvent>> events;
113 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 5 * NS_PER_SEC,
114 attributionUids1, attributionTags1,
115 "wl1")); // Not kept.
116 events.push_back(CreateScreenStateChangedEvent(
117 bucketStartTimeNs + 10 * NS_PER_SEC,
118 android::view::DISPLAY_STATE_ON)); // Condition true for change.
119 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 15 * NS_PER_SEC, attributionUids1,
120 attributionTags1,
121 "sync1")); // Kept for persist & remove.
122 events.push_back(CreateBatteryStateChangedEvent(
123 bucketStartTimeNs + 20 * NS_PER_SEC,
124 BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE)); // Condition true for preserve.
125 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 25 * NS_PER_SEC,
126 attributionUids1, attributionTags1,
127 "wl2")); // Kept by persist and change.
128 events.push_back(CreateScreenStateChangedEvent(
129 bucketStartTimeNs + 30 * NS_PER_SEC,
130 android::view::DISPLAY_STATE_OFF)); // Condition false for change.
131 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 35 * NS_PER_SEC, attributionUids1,
132 attributionTags1,
133 "sync2")); // Kept for persist & remove.
134 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 40 * NS_PER_SEC,
135 attributionUids1, attributionTags1,
136 "wl3")); // Kept by persist.
137
138 // Send log events to StatsLogProcessor.
139 for (auto& event : events) {
140 processor->OnLogEvent(event.get());
141 }
142
143 // Do update. Add matchers/conditions in different order to force indices to change.
144 StatsdConfig newConfig;
145 newConfig.add_allowed_log_source("AID_ROOT");
146
147 *newConfig.add_atom_matcher() = screenOnMatcher;
148 *newConfig.add_atom_matcher() = batteryPluggedUsbMatcher;
149 *newConfig.add_atom_matcher() = syncStartMatcher;
150 *newConfig.add_atom_matcher() = *combinationMatcher;
151 *newConfig.add_atom_matcher() = wakelockAcquireMatcher;
152 *newConfig.add_atom_matcher() = screenOffMatcher;
153 *newConfig.add_atom_matcher() = unpluggedMatcher;
154 *newConfig.add_predicate() = *combinationPredicate;
155 *newConfig.add_predicate() = unpluggedPredicate;
156 *newConfig.add_predicate() = screenOnPredicate;
157
158 // Add metrics. Note that the condition of eventChange will go from false to true.
159 eventChange.set_condition(unpluggedPredicate.id());
160 *newConfig.add_event_metric() = eventChange;
161 EventMetric eventNew = createEventMetric("ScreenOn", screenOnMatcher.id(), nullopt);
162 *newConfig.add_event_metric() = eventNew;
163 *newConfig.add_event_metric() = eventPersist;
164
165 int64_t updateTimeNs = bucketStartTimeNs + 60 * NS_PER_SEC;
166 processor->OnConfigUpdated(updateTimeNs, key, newConfig);
167
168 // Send events after the update.
169 events.clear();
170 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 65 * NS_PER_SEC,
171 attributionUids1, attributionTags1,
172 "wl4")); // Kept by preserve & change.
173 events.push_back(CreateBatteryStateChangedEvent(
174 bucketStartTimeNs + 70 * NS_PER_SEC,
175 BatteryPluggedStateEnum::BATTERY_PLUGGED_USB)); // All conditions are false.
176 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 75 * NS_PER_SEC,
177 attributionUids1, attributionTags1,
178 "wl5")); // Not kept.
179 events.push_back(CreateScreenStateChangedEvent(
180 bucketStartTimeNs + 80 * NS_PER_SEC,
181 android::view::DISPLAY_STATE_ON)); // Condition true for preserve, event kept by new.
182 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 85 * NS_PER_SEC,
183 attributionUids1, attributionTags1,
184 "wl6")); // Kept by preserve.
185 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 90 * NS_PER_SEC, attributionUids1,
186 attributionTags1, "sync3")); // Kept by preserve.
187
188 // Send log events to StatsLogProcessor.
189 for (auto& event : events) {
190 processor->OnLogEvent(event.get());
191 }
192 uint64_t dumpTimeNs = bucketStartTimeNs + 100 * NS_PER_SEC;
193 ConfigMetricsReportList reports;
194 vector<uint8_t> buffer;
195 processor->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, FAST, &buffer);
196 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
197 backfillDimensionPath(&reports);
198 backfillStringInReport(&reports);
199 backfillStartEndTimestamp(&reports);
200 ASSERT_EQ(reports.reports_size(), 2);
201
202 // Report from before update.
203 ConfigMetricsReport report = reports.reports(0);
204 ASSERT_EQ(report.metrics_size(), 3);
205 // Event remove. Captured sync events. There were 2 syncs before the update.
206 StatsLogReport eventRemoveBefore = report.metrics(0);
207 EXPECT_EQ(eventRemoveBefore.metric_id(), eventRemove.id());
208 EXPECT_TRUE(eventRemoveBefore.has_event_metrics());
209 ASSERT_EQ(eventRemoveBefore.event_metrics().data_size(), 2);
210 auto data = eventRemoveBefore.event_metrics().data(0);
211 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 15 * NS_PER_SEC);
212 EXPECT_EQ(data.atom().sync_state_changed().sync_name(), "sync1");
213 data = eventRemoveBefore.event_metrics().data(1);
214 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 35 * NS_PER_SEC);
215 EXPECT_EQ(data.atom().sync_state_changed().sync_name(), "sync2");
216
217 // Captured wakelocks & syncs while screen on or unplugged. There were 2 wakelocks and 2 syncs.
218 StatsLogReport eventPersistBefore = report.metrics(1);
219 EXPECT_EQ(eventPersistBefore.metric_id(), eventPersist.id());
220 EXPECT_TRUE(eventPersistBefore.has_event_metrics());
221 ASSERT_EQ(eventPersistBefore.event_metrics().data_size(), 3);
222 data = eventPersistBefore.event_metrics().data(0);
223 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 25 * NS_PER_SEC);
224 EXPECT_EQ(data.atom().wakelock_state_changed().tag(), "wl2");
225 data = eventPersistBefore.event_metrics().data(1);
226 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 35 * NS_PER_SEC);
227 EXPECT_EQ(data.atom().sync_state_changed().sync_name(), "sync2");
228 data = eventPersistBefore.event_metrics().data(2);
229 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 40 * NS_PER_SEC);
230 EXPECT_EQ(data.atom().wakelock_state_changed().tag(), "wl3");
231
232 // Captured wakelock events while screen on. There was 1 before the update.
233 StatsLogReport eventChangeBefore = report.metrics(2);
234 EXPECT_EQ(eventChangeBefore.metric_id(), eventChange.id());
235 EXPECT_TRUE(eventChangeBefore.has_event_metrics());
236 ASSERT_EQ(eventChangeBefore.event_metrics().data_size(), 1);
237 data = eventChangeBefore.event_metrics().data(0);
238 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 25 * NS_PER_SEC);
239 EXPECT_EQ(data.atom().wakelock_state_changed().tag(), "wl2");
240
241 // Report from after update.
242 report = reports.reports(1);
243 ASSERT_EQ(report.metrics_size(), 3);
244 // Captured wakelocks while unplugged. There was 1 after the update.
245 StatsLogReport eventChangeAfter = report.metrics(0);
246 EXPECT_EQ(eventChangeAfter.metric_id(), eventChange.id());
247 EXPECT_TRUE(eventChangeAfter.has_event_metrics());
248 ASSERT_EQ(eventChangeAfter.event_metrics().data_size(), 1);
249 data = eventChangeAfter.event_metrics().data(0);
250 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 65 * NS_PER_SEC);
251 EXPECT_EQ(data.atom().wakelock_state_changed().tag(), "wl4");
252
253 // Captured screen on events. There was 1 after the update.
254 StatsLogReport eventNewAfter = report.metrics(1);
255 EXPECT_EQ(eventNewAfter.metric_id(), eventNew.id());
256 EXPECT_TRUE(eventNewAfter.has_event_metrics());
257 ASSERT_EQ(eventNewAfter.event_metrics().data_size(), 1);
258 data = eventNewAfter.event_metrics().data(0);
259 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 80 * NS_PER_SEC);
260 EXPECT_EQ(data.atom().screen_state_changed().state(), android::view::DISPLAY_STATE_ON);
261
262 // There were 2 wakelocks and 1 sync after the update while the condition was true.
263 StatsLogReport eventPersistAfter = report.metrics(2);
264 EXPECT_EQ(eventPersistAfter.metric_id(), eventPersist.id());
265 EXPECT_TRUE(eventPersistAfter.has_event_metrics());
266 ASSERT_EQ(eventPersistAfter.event_metrics().data_size(), 3);
267 data = eventPersistAfter.event_metrics().data(0);
268 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 65 * NS_PER_SEC);
269 EXPECT_EQ(data.atom().wakelock_state_changed().tag(), "wl4");
270 data = eventPersistAfter.event_metrics().data(1);
271 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 85 * NS_PER_SEC);
272 EXPECT_EQ(data.atom().wakelock_state_changed().tag(), "wl6");
273 data = eventPersistAfter.event_metrics().data(2);
274 EXPECT_EQ(data.elapsed_timestamp_nanos(), bucketStartTimeNs + 90 * NS_PER_SEC);
275 EXPECT_EQ(data.atom().sync_state_changed().sync_name(), "sync3");
276 }
277
TEST_F(ConfigUpdateE2eTest,TestCountMetric)278 TEST_F(ConfigUpdateE2eTest, TestCountMetric) {
279 StatsdConfig config;
280 config.add_allowed_log_source("AID_ROOT");
281
282 AtomMatcher syncStartMatcher = CreateSyncStartAtomMatcher();
283 *config.add_atom_matcher() = syncStartMatcher;
284 AtomMatcher wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
285 *config.add_atom_matcher() = wakelockAcquireMatcher;
286 AtomMatcher wakelockReleaseMatcher = CreateReleaseWakelockAtomMatcher();
287 *config.add_atom_matcher() = wakelockReleaseMatcher;
288 AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
289 *config.add_atom_matcher() = screenOnMatcher;
290 AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
291 *config.add_atom_matcher() = screenOffMatcher;
292
293 Predicate holdingWakelockPredicate = CreateHoldingWakelockPredicate();
294 // The predicate is dimensioning by first attribution node by uid.
295 *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() =
296 CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
297 *config.add_predicate() = holdingWakelockPredicate;
298
299 Predicate screenOnPredicate = CreateScreenIsOnPredicate();
300 *config.add_predicate() = screenOnPredicate;
301
302 Predicate* combination = config.add_predicate();
303 combination->set_id(StringToId("ScreenOnAndHoldingWL)"));
304 combination->mutable_combination()->set_operation(LogicalOperation::AND);
305 addPredicateToPredicateCombination(screenOnPredicate, combination);
306 addPredicateToPredicateCombination(holdingWakelockPredicate, combination);
307
308 State uidProcessState = CreateUidProcessState();
309 *config.add_state() = uidProcessState;
310
311 CountMetric countPersist =
312 createCountMetric("CountSyncPerUidWhileScreenOnHoldingWLSliceProcessState",
313 syncStartMatcher.id(), combination->id(), {uidProcessState.id()});
314 *countPersist.mutable_dimensions_in_what() =
315 CreateAttributionUidDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST});
316 // Links between sync state atom and condition of uid is holding wakelock.
317 MetricConditionLink* links = countPersist.add_links();
318 links->set_condition(holdingWakelockPredicate.id());
319 *links->mutable_fields_in_what() =
320 CreateAttributionUidDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST});
321 *links->mutable_fields_in_condition() =
322 CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
323 MetricStateLink* stateLink = countPersist.add_state_link();
324 stateLink->set_state_atom_id(util::UID_PROCESS_STATE_CHANGED);
325 *stateLink->mutable_fields_in_what() =
326 CreateAttributionUidDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST});
327 *stateLink->mutable_fields_in_state() =
328 CreateDimensions(util::UID_PROCESS_STATE_CHANGED, {1 /*uid*/});
329
330 CountMetric countChange = createCountMetric("Count*WhileScreenOn", syncStartMatcher.id(),
331 screenOnPredicate.id(), {});
332 CountMetric countRemove = createCountMetric("CountSync", syncStartMatcher.id(), nullopt, {});
333 *config.add_count_metric() = countRemove;
334 *config.add_count_metric() = countPersist;
335 *config.add_count_metric() = countChange;
336
337 ConfigKey key(123, 987);
338 uint64_t bucketStartTimeNs = 10000000000; // 0:10
339 uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(TEN_MINUTES) * 1000000LL;
340 sp<StatsLogProcessor> processor =
341 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, key);
342
343 int app1Uid = 123, app2Uid = 456;
344 vector<int> attributionUids1 = {app1Uid};
345 vector<string> attributionTags1 = {"App1"};
346 vector<int> attributionUids2 = {app2Uid};
347 vector<string> attributionTags2 = {"App2"};
348
349 // Initialize log events before update. Counts are for countPersist since others are simpler.
350 std::vector<std::unique_ptr<LogEvent>> events;
351 events.push_back(CreateUidProcessStateChangedEvent(
352 bucketStartTimeNs + 2 * NS_PER_SEC, app1Uid,
353 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND));
354 events.push_back(CreateUidProcessStateChangedEvent(
355 bucketStartTimeNs + 3 * NS_PER_SEC, app2Uid,
356 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));
357 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 5 * NS_PER_SEC, attributionUids1,
358 attributionTags1, "sync_name")); // Not counted.
359 events.push_back(
360 CreateScreenStateChangedEvent(bucketStartTimeNs + 10 * NS_PER_SEC,
361 android::view::DisplayStateEnum::DISPLAY_STATE_ON));
362 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 15 * NS_PER_SEC,
363 attributionUids1, attributionTags1, "wl1"));
364 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 20 * NS_PER_SEC, attributionUids1,
365 attributionTags1, "sync_name")); // Counted. uid1 = 1.
366 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 21 * NS_PER_SEC, attributionUids2,
367 attributionTags2, "sync_name")); // Not counted.
368 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 25 * NS_PER_SEC,
369 attributionUids2, attributionTags2, "wl2"));
370 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 30 * NS_PER_SEC, attributionUids1,
371 attributionTags1, "sync_name")); // Counted. uid1 = 2.
372 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 31 * NS_PER_SEC, attributionUids2,
373 attributionTags2, "sync_name")); // Counted. uid2 = 1
374 events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 35 * NS_PER_SEC,
375 attributionUids1, attributionTags1, "wl1"));
376 // Send log events to StatsLogProcessor.
377 for (auto& event : events) {
378 processor->OnLogEvent(event.get());
379 }
380
381 // Do update. Add matchers/conditions in different order to force indices to change.
382 StatsdConfig newConfig;
383 newConfig.add_allowed_log_source("AID_ROOT");
384
385 *newConfig.add_atom_matcher() = screenOnMatcher;
386 *newConfig.add_atom_matcher() = screenOffMatcher;
387 *newConfig.add_atom_matcher() = syncStartMatcher;
388 *newConfig.add_atom_matcher() = wakelockAcquireMatcher;
389 *newConfig.add_atom_matcher() = wakelockReleaseMatcher;
390 *newConfig.add_predicate() = *combination;
391 *newConfig.add_predicate() = holdingWakelockPredicate;
392 *newConfig.add_predicate() = screenOnPredicate;
393 *newConfig.add_state() = uidProcessState;
394
395 countChange.set_what(screenOnMatcher.id());
396 *newConfig.add_count_metric() = countChange;
397 CountMetric countNew = createCountMetric("CountWlWhileScreenOn", wakelockAcquireMatcher.id(),
398 screenOnPredicate.id(), {});
399 *newConfig.add_count_metric() = countNew;
400 *newConfig.add_count_metric() = countPersist;
401
402 int64_t updateTimeNs = bucketStartTimeNs + 60 * NS_PER_SEC;
403 processor->OnConfigUpdated(updateTimeNs, key, newConfig);
404
405 // Send events after the update. Counts reset to 0 since this is a new bucket.
406 events.clear();
407 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 65 * NS_PER_SEC, attributionUids1,
408 attributionTags1, "sync_name")); // Not counted.
409 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 66 * NS_PER_SEC, attributionUids2,
410 attributionTags2, "sync_name")); // Counted. uid2 = 1.
411 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 70 * NS_PER_SEC,
412 attributionUids1, attributionTags1, "wl1"));
413 events.push_back(
414 CreateScreenStateChangedEvent(bucketStartTimeNs + 75 * NS_PER_SEC,
415 android::view::DisplayStateEnum::DISPLAY_STATE_OFF));
416 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 80 * NS_PER_SEC, attributionUids2,
417 attributionTags2, "sync_name")); // Not counted.
418 events.push_back(
419 CreateScreenStateChangedEvent(bucketStartTimeNs + 85 * NS_PER_SEC,
420 android::view::DisplayStateEnum::DISPLAY_STATE_ON));
421 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 90 * NS_PER_SEC, attributionUids1,
422 attributionTags1, "sync_name")); // Counted. uid1 = 1.
423 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 11 * NS_PER_SEC, attributionUids2,
424 attributionTags2, "sync_name")); // Counted. uid2 = 2.
425 // Flushes bucket.
426 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + NS_PER_SEC,
427 attributionUids1, attributionTags1, "wl2"));
428 // Send log events to StatsLogProcessor.
429 for (auto& event : events) {
430 processor->OnLogEvent(event.get());
431 }
432 uint64_t dumpTimeNs = bucketStartTimeNs + bucketSizeNs + 10 * NS_PER_SEC;
433 ConfigMetricsReportList reports;
434 vector<uint8_t> buffer;
435 processor->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, FAST, &buffer);
436 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
437 backfillDimensionPath(&reports);
438 backfillStringInReport(&reports);
439 backfillStartEndTimestamp(&reports);
440 ASSERT_EQ(reports.reports_size(), 2);
441
442 // Report from before update.
443 ConfigMetricsReport report = reports.reports(0);
444 ASSERT_EQ(report.metrics_size(), 3);
445 // Count syncs. There were 5 syncs before the update.
446 StatsLogReport countRemoveBefore = report.metrics(0);
447 EXPECT_EQ(countRemoveBefore.metric_id(), countRemove.id());
448 EXPECT_TRUE(countRemoveBefore.has_count_metrics());
449 ASSERT_EQ(countRemoveBefore.count_metrics().data_size(), 1);
450 auto data = countRemoveBefore.count_metrics().data(0);
451 ASSERT_EQ(data.bucket_info_size(), 1);
452 ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, updateTimeNs, 5);
453
454 // Uid 1 had 2 syncs, uid 2 had 1 sync.
455 StatsLogReport countPersistBefore = report.metrics(1);
456 EXPECT_EQ(countPersistBefore.metric_id(), countPersist.id());
457 EXPECT_TRUE(countPersistBefore.has_count_metrics());
458 StatsLogReport::CountMetricDataWrapper countMetrics;
459 sortMetricDataByDimensionsValue(countPersistBefore.count_metrics(), &countMetrics);
460 ASSERT_EQ(countMetrics.data_size(), 2);
461 data = countMetrics.data(0);
462 ValidateAttributionUidDimension(data.dimensions_in_what(), util::SYNC_STATE_CHANGED, app1Uid);
463 ValidateStateValue(data.slice_by_state(), util::UID_PROCESS_STATE_CHANGED,
464 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND);
465 ASSERT_EQ(data.bucket_info_size(), 1);
466 ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, updateTimeNs, 2);
467
468 data = countMetrics.data(1);
469 ValidateAttributionUidDimension(data.dimensions_in_what(), util::SYNC_STATE_CHANGED, app2Uid);
470 ValidateStateValue(data.slice_by_state(), util::UID_PROCESS_STATE_CHANGED,
471 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND);
472 ASSERT_EQ(data.bucket_info_size(), 1);
473 ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, updateTimeNs, 1);
474
475 // Counts syncs while screen on. There were 4 before the update.
476 StatsLogReport countChangeBefore = report.metrics(2);
477 EXPECT_EQ(countChangeBefore.metric_id(), countChange.id());
478 EXPECT_TRUE(countChangeBefore.has_count_metrics());
479 ASSERT_EQ(countChangeBefore.count_metrics().data_size(), 1);
480 data = countChangeBefore.count_metrics().data(0);
481 ASSERT_EQ(data.bucket_info_size(), 1);
482 ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, updateTimeNs, 4);
483
484 // Report from after update.
485 report = reports.reports(1);
486 ASSERT_EQ(report.metrics_size(), 3);
487 // Count screen on while screen is on. There was 1 after the update.
488 StatsLogReport countChangeAfter = report.metrics(0);
489 EXPECT_EQ(countChangeAfter.metric_id(), countChange.id());
490 EXPECT_TRUE(countChangeAfter.has_count_metrics());
491 ASSERT_EQ(countChangeAfter.count_metrics().data_size(), 1);
492 data = countChangeAfter.count_metrics().data(0);
493 ASSERT_EQ(data.bucket_info_size(), 1);
494 ValidateCountBucket(data.bucket_info(0), updateTimeNs, bucketStartTimeNs + bucketSizeNs, 1);
495
496 // Count wl acquires while screen on. There were 2, one in each bucket.
497 StatsLogReport countNewAfter = report.metrics(1);
498 EXPECT_EQ(countNewAfter.metric_id(), countNew.id());
499 EXPECT_TRUE(countNewAfter.has_count_metrics());
500 ASSERT_EQ(countNewAfter.count_metrics().data_size(), 1);
501 data = countNewAfter.count_metrics().data(0);
502 ASSERT_EQ(data.bucket_info_size(), 2);
503 ValidateCountBucket(data.bucket_info(0), updateTimeNs, bucketStartTimeNs + bucketSizeNs, 1);
504 ValidateCountBucket(data.bucket_info(1), bucketStartTimeNs + bucketSizeNs, dumpTimeNs, 1);
505
506 // Uid 1 had 1 sync, uid 2 had 2 syncs.
507 StatsLogReport countPersistAfter = report.metrics(2);
508 EXPECT_EQ(countPersistAfter.metric_id(), countPersist.id());
509 EXPECT_TRUE(countPersistAfter.has_count_metrics());
510 countMetrics.Clear();
511 sortMetricDataByDimensionsValue(countPersistAfter.count_metrics(), &countMetrics);
512 ASSERT_EQ(countMetrics.data_size(), 2);
513 data = countMetrics.data(0);
514 ValidateAttributionUidDimension(data.dimensions_in_what(), util::SYNC_STATE_CHANGED, app1Uid);
515 ValidateStateValue(data.slice_by_state(), util::UID_PROCESS_STATE_CHANGED,
516 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND);
517 ASSERT_EQ(data.bucket_info_size(), 1);
518 ValidateCountBucket(data.bucket_info(0), updateTimeNs, bucketStartTimeNs + bucketSizeNs, 1);
519
520 data = countMetrics.data(1);
521 ValidateAttributionUidDimension(data.dimensions_in_what(), util::SYNC_STATE_CHANGED, app2Uid);
522 ValidateStateValue(data.slice_by_state(), util::UID_PROCESS_STATE_CHANGED,
523 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND);
524 ASSERT_EQ(data.bucket_info_size(), 1);
525 ValidateCountBucket(data.bucket_info(0), updateTimeNs, bucketStartTimeNs + bucketSizeNs, 2);
526 }
527
TEST_F(ConfigUpdateE2eTest,TestDurationMetric)528 TEST_F(ConfigUpdateE2eTest, TestDurationMetric) {
529 StatsdConfig config;
530 config.add_allowed_log_source("AID_ROOT");
531
532 AtomMatcher syncStartMatcher = CreateSyncStartAtomMatcher();
533 *config.add_atom_matcher() = syncStartMatcher;
534 AtomMatcher syncStopMatcher = CreateSyncEndAtomMatcher();
535 *config.add_atom_matcher() = syncStopMatcher;
536 AtomMatcher wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
537 *config.add_atom_matcher() = wakelockAcquireMatcher;
538 AtomMatcher wakelockReleaseMatcher = CreateReleaseWakelockAtomMatcher();
539 *config.add_atom_matcher() = wakelockReleaseMatcher;
540 AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
541 *config.add_atom_matcher() = screenOnMatcher;
542 AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
543 *config.add_atom_matcher() = screenOffMatcher;
544
545 Predicate holdingWakelockPredicate = CreateHoldingWakelockPredicate();
546 // The predicate is dimensioning by first attribution node by uid.
547 *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() =
548 CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
549 *config.add_predicate() = holdingWakelockPredicate;
550
551 Predicate screenOnPredicate = CreateScreenIsOnPredicate();
552 *config.add_predicate() = screenOnPredicate;
553
554 Predicate syncPredicate = CreateIsSyncingPredicate();
555 // The predicate is dimensioning by first attribution node by uid.
556 *syncPredicate.mutable_simple_predicate()->mutable_dimensions() =
557 CreateAttributionUidDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST});
558 *config.add_predicate() = syncPredicate;
559
560 State uidProcessState = CreateUidProcessState();
561 *config.add_state() = uidProcessState;
562
563 DurationMetric durationSumPersist =
564 createDurationMetric("DurSyncPerUidWhileHoldingWLSliceProcessState", syncPredicate.id(),
565 holdingWakelockPredicate.id(), {uidProcessState.id()});
566 *durationSumPersist.mutable_dimensions_in_what() =
567 CreateAttributionUidDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST});
568 // Links between sync state atom and condition of uid is holding wakelock.
569 MetricConditionLink* links = durationSumPersist.add_links();
570 links->set_condition(holdingWakelockPredicate.id());
571 *links->mutable_fields_in_what() =
572 CreateAttributionUidDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST});
573 *links->mutable_fields_in_condition() =
574 CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
575 MetricStateLink* stateLink = durationSumPersist.add_state_link();
576 stateLink->set_state_atom_id(util::UID_PROCESS_STATE_CHANGED);
577 *stateLink->mutable_fields_in_what() =
578 CreateAttributionUidDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST});
579 *stateLink->mutable_fields_in_state() =
580 CreateDimensions(util::UID_PROCESS_STATE_CHANGED, {1 /*uid*/});
581
582 DurationMetric durationMaxPersist =
583 createDurationMetric("DurMaxSyncPerUidWhileHoldingWL", syncPredicate.id(),
584 holdingWakelockPredicate.id(), {});
585 durationMaxPersist.set_aggregation_type(DurationMetric::MAX_SPARSE);
586 *durationMaxPersist.mutable_dimensions_in_what() =
587 CreateAttributionUidDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST});
588 // Links between sync state atom and condition of uid is holding wakelock.
589 links = durationMaxPersist.add_links();
590 links->set_condition(holdingWakelockPredicate.id());
591 *links->mutable_fields_in_what() =
592 CreateAttributionUidDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST});
593 *links->mutable_fields_in_condition() =
594 CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
595
596 DurationMetric durationChange = createDurationMetric("Dur*WhileScreenOn", syncPredicate.id(),
597 screenOnPredicate.id(), {});
598 DurationMetric durationRemove =
599 createDurationMetric("DurScreenOn", screenOnPredicate.id(), nullopt, {});
600 *config.add_duration_metric() = durationMaxPersist;
601 *config.add_duration_metric() = durationRemove;
602 *config.add_duration_metric() = durationSumPersist;
603 *config.add_duration_metric() = durationChange;
604
605 ConfigKey key(123, 987);
606 uint64_t bucketStartTimeNs = 10000000000; // 0:10
607 uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(TEN_MINUTES) * 1000000LL;
608 sp<StatsLogProcessor> processor =
609 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, key);
610
611 int app1Uid = 123, app2Uid = 456, app3Uid = 789;
612 vector<int> attributionUids1 = {app1Uid};
613 vector<string> attributionTags1 = {"App1"};
614 vector<int> attributionUids2 = {app2Uid};
615 vector<string> attributionTags2 = {"App2"};
616 vector<int> attributionUids3 = {app3Uid};
617 vector<string> attributionTags3 = {"App3"};
618
619 // Initialize log events before update. Comments provided for durations of persisted metrics.
620 std::vector<std::unique_ptr<LogEvent>> events;
621 events.push_back(CreateUidProcessStateChangedEvent(
622 bucketStartTimeNs + 2 * NS_PER_SEC, app1Uid,
623 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND));
624 events.push_back(CreateUidProcessStateChangedEvent(
625 bucketStartTimeNs + 3 * NS_PER_SEC, app2Uid,
626 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));
627 events.push_back(CreateScreenStateChangedEvent(
628 bucketStartTimeNs + 5 * NS_PER_SEC, android::view::DisplayStateEnum::DISPLAY_STATE_ON));
629 events.push_back(CreateUidProcessStateChangedEvent(
630 bucketStartTimeNs + 6 * NS_PER_SEC, app3Uid,
631 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND));
632 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 10 * NS_PER_SEC, attributionUids1,
633 attributionTags1, "sync_name")); // uid1 paused.
634 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 15 * NS_PER_SEC,
635 attributionUids2, attributionTags2,
636 "wl2")); // uid2 cond true.
637 events.push_back(
638 CreateScreenStateChangedEvent(bucketStartTimeNs + 20 * NS_PER_SEC,
639 android::view::DisplayStateEnum::DISPLAY_STATE_OFF));
640 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 25 * NS_PER_SEC, attributionUids2,
641 attributionTags2, "sync_name")); // Uid 2 start t=25.
642 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 27 * NS_PER_SEC,
643 attributionUids1, attributionTags1,
644 "wl1")); // Uid 1 start t=27.
645 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 35 * NS_PER_SEC, attributionUids3,
646 attributionTags3, "sync_name")); // Uid 3 paused.
647 events.push_back(
648 CreateScreenStateChangedEvent(bucketStartTimeNs + 40 * NS_PER_SEC,
649 android::view::DisplayStateEnum::DISPLAY_STATE_ON));
650 events.push_back(CreateSyncEndEvent(bucketStartTimeNs + 45 * NS_PER_SEC, attributionUids2,
651 attributionTags2,
652 "sync_name")); // Uid 2 stop. sum/max = 20.
653 // Send log events to StatsLogProcessor.
654 for (auto& event : events) {
655 processor->OnLogEvent(event.get());
656 }
657
658 // Do update. Add matchers/conditions in different order to force indices to change.
659 StatsdConfig newConfig;
660 newConfig.add_allowed_log_source("AID_ROOT");
661
662 *newConfig.add_atom_matcher() = wakelockReleaseMatcher;
663 *newConfig.add_atom_matcher() = syncStopMatcher;
664 *newConfig.add_atom_matcher() = screenOnMatcher;
665 *newConfig.add_atom_matcher() = screenOffMatcher;
666 *newConfig.add_atom_matcher() = syncStartMatcher;
667 *newConfig.add_atom_matcher() = wakelockAcquireMatcher;
668 *newConfig.add_predicate() = syncPredicate;
669 *newConfig.add_predicate() = screenOnPredicate;
670 *newConfig.add_predicate() = holdingWakelockPredicate;
671 *newConfig.add_state() = uidProcessState;
672
673 durationChange.set_what(holdingWakelockPredicate.id());
674 *newConfig.add_duration_metric() = durationChange;
675 DurationMetric durationNew =
676 createDurationMetric("DurationSync", syncPredicate.id(), nullopt, {});
677 *newConfig.add_duration_metric() = durationNew;
678 *newConfig.add_duration_metric() = durationMaxPersist;
679 *newConfig.add_duration_metric() = durationSumPersist;
680
681 // At update, only uid 1 is syncing & holding a wakelock, duration=33. Max is paused for uid3.
682 // Before the update, only uid2 will report a duration for max, since others are started/paused.
683 int64_t updateTimeNs = bucketStartTimeNs + 60 * NS_PER_SEC;
684 processor->OnConfigUpdated(updateTimeNs, key, newConfig);
685
686 // Send events after the update.
687 events.clear();
688 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 65 * NS_PER_SEC,
689 attributionUids3, attributionTags3,
690 "wl3")); // Uid3 start t=65.
691 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 70 * NS_PER_SEC, attributionUids2,
692 attributionTags2, "sync_name")); // Uid2 start t=70.
693 events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 75 * NS_PER_SEC,
694 attributionUids1, attributionTags1,
695 "wl1")); // Uid1 Pause. Dur = 15.
696 events.push_back(
697 CreateScreenStateChangedEvent(bucketStartTimeNs + 81 * NS_PER_SEC,
698 android::view::DisplayStateEnum::DISPLAY_STATE_OFF));
699 events.push_back(CreateUidProcessStateChangedEvent(
700 bucketStartTimeNs + 85 * NS_PER_SEC, app3Uid,
701 android::app::ProcessStateEnum::
702 PROCESS_STATE_IMPORTANT_FOREGROUND)); // Uid3 Sum in BG: 20. FG starts. Max is
703 // unchanged.
704 events.push_back(CreateSyncEndEvent(bucketStartTimeNs + 90 * NS_PER_SEC, attributionUids3,
705 attributionTags3,
706 "sync_name")); // Uid3 stop. Sum in FG: 5. MAX: 25.
707
708 // Flushes bucket. Sum: uid1=15, uid2=bucketSize - 70, uid3 = 20 in FG, 5 in BG. Max: uid3=25,
709 // others don't report.
710 events.push_back(CreateSyncEndEvent(bucketStartTimeNs + bucketSizeNs + NS_PER_SEC,
711 attributionUids1, attributionTags1,
712 "sync_name")); // Uid1 stop. Max=15+33=48, Sum is 0.
713
714 // Send log events to StatsLogProcessor.
715 for (auto& event : events) {
716 processor->OnLogEvent(event.get());
717 }
718 uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
719 uint64_t dumpTimeNs = bucketStartTimeNs + bucketSizeNs + 10 * NS_PER_SEC;
720 ConfigMetricsReportList reports;
721 vector<uint8_t> buffer;
722 // In the partial bucket, Sum for uid2 = 10, Max for Uid1 = 48. Rest are unreported.
723 processor->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, FAST, &buffer);
724 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
725 backfillDimensionPath(&reports);
726 backfillStringInReport(&reports);
727 backfillStartEndTimestamp(&reports);
728 ASSERT_EQ(reports.reports_size(), 2);
729
730 // Report from before update.
731 ConfigMetricsReport report = reports.reports(0);
732 ASSERT_EQ(report.metrics_size(), 4);
733 // Max duration of syncs per uid while uid holding WL. Only uid2 should have data.
734 StatsLogReport durationMaxPersistBefore = report.metrics(0);
735 EXPECT_EQ(durationMaxPersistBefore.metric_id(), durationMaxPersist.id());
736 EXPECT_TRUE(durationMaxPersistBefore.has_duration_metrics());
737 StatsLogReport::DurationMetricDataWrapper durationMetrics;
738 sortMetricDataByDimensionsValue(durationMaxPersistBefore.duration_metrics(), &durationMetrics);
739 ASSERT_EQ(durationMetrics.data_size(), 1);
740 auto data = durationMetrics.data(0);
741 ValidateAttributionUidDimension(data.dimensions_in_what(), util::SYNC_STATE_CHANGED, app2Uid);
742 ASSERT_EQ(data.bucket_info_size(), 1);
743 ValidateDurationBucket(data.bucket_info(0), bucketStartTimeNs, updateTimeNs, 20 * NS_PER_SEC);
744
745 // Screen on time. ON: 5, OFF: 20, ON: 40. Update: 60. Result: 35
746 StatsLogReport durationRemoveBefore = report.metrics(1);
747 EXPECT_EQ(durationRemoveBefore.metric_id(), durationRemove.id());
748 EXPECT_TRUE(durationRemoveBefore.has_duration_metrics());
749 durationMetrics.Clear();
750 sortMetricDataByDimensionsValue(durationRemoveBefore.duration_metrics(), &durationMetrics);
751 ASSERT_EQ(durationMetrics.data_size(), 1);
752 data = durationMetrics.data(0);
753 ASSERT_EQ(data.bucket_info_size(), 1);
754 ValidateDurationBucket(data.bucket_info(0), bucketStartTimeNs, updateTimeNs, 35 * NS_PER_SEC);
755
756 // Duration of syncs per uid while uid holding WL, slice screen. Uid1=33, uid2=20.
757 StatsLogReport durationSumPersistBefore = report.metrics(2);
758 EXPECT_EQ(durationSumPersistBefore.metric_id(), durationSumPersist.id());
759 EXPECT_TRUE(durationSumPersistBefore.has_duration_metrics());
760 durationMetrics.Clear();
761 sortMetricDataByDimensionsValue(durationSumPersistBefore.duration_metrics(), &durationMetrics);
762 ASSERT_EQ(durationMetrics.data_size(), 2);
763 data = durationMetrics.data(0);
764 ValidateAttributionUidDimension(data.dimensions_in_what(), util::SYNC_STATE_CHANGED, app1Uid);
765 ValidateStateValue(data.slice_by_state(), util::UID_PROCESS_STATE_CHANGED,
766 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND);
767 ASSERT_EQ(data.bucket_info_size(), 1);
768 ValidateDurationBucket(data.bucket_info(0), bucketStartTimeNs, updateTimeNs, 33 * NS_PER_SEC);
769
770 data = durationMetrics.data(1);
771 ValidateAttributionUidDimension(data.dimensions_in_what(), util::SYNC_STATE_CHANGED, app2Uid);
772 ValidateStateValue(data.slice_by_state(), util::UID_PROCESS_STATE_CHANGED,
773 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND);
774 ASSERT_EQ(data.bucket_info_size(), 1);
775 ValidateDurationBucket(data.bucket_info(0), bucketStartTimeNs, updateTimeNs, 20 * NS_PER_SEC);
776
777 // Duration of syncs while screen on. Start: 10, pause: 20, start: 40 Update: 60. Total: 30.
778 StatsLogReport durationChangeBefore = report.metrics(3);
779 EXPECT_EQ(durationChangeBefore.metric_id(), durationChange.id());
780 EXPECT_TRUE(durationChangeBefore.has_duration_metrics());
781 durationMetrics.Clear();
782 sortMetricDataByDimensionsValue(durationChangeBefore.duration_metrics(), &durationMetrics);
783 ASSERT_EQ(durationMetrics.data_size(), 1);
784 data = durationMetrics.data(0);
785 ASSERT_EQ(data.bucket_info_size(), 1);
786 ValidateDurationBucket(data.bucket_info(0), bucketStartTimeNs, updateTimeNs, 30 * NS_PER_SEC);
787
788 // Report from after update.
789 report = reports.reports(1);
790 ASSERT_EQ(report.metrics_size(), 4);
791 // Duration of WL while screen on. Update: 60, pause: 81. Total: 21.
792 StatsLogReport durationChangeAfter = report.metrics(0);
793 EXPECT_EQ(durationChangeAfter.metric_id(), durationChange.id());
794 EXPECT_TRUE(durationChangeAfter.has_duration_metrics());
795 durationMetrics.Clear();
796 sortMetricDataByDimensionsValue(durationChangeAfter.duration_metrics(), &durationMetrics);
797 ASSERT_EQ(durationMetrics.data_size(), 1);
798 data = durationMetrics.data(0);
799 ASSERT_EQ(data.bucket_info_size(), 1);
800 ValidateDurationBucket(data.bucket_info(0), updateTimeNs, bucketEndTimeNs, 21 * NS_PER_SEC);
801
802 // Duration of syncs. Always true since at least 1 uid is always syncing.
803 StatsLogReport durationNewAfter = report.metrics(1);
804 EXPECT_EQ(durationNewAfter.metric_id(), durationNew.id());
805 EXPECT_TRUE(durationNewAfter.has_duration_metrics());
806 durationMetrics.Clear();
807 sortMetricDataByDimensionsValue(durationNewAfter.duration_metrics(), &durationMetrics);
808 ASSERT_EQ(durationMetrics.data_size(), 1);
809 data = durationMetrics.data(0);
810 ASSERT_EQ(data.bucket_info_size(), 2);
811 ValidateDurationBucket(data.bucket_info(0), updateTimeNs, bucketEndTimeNs,
812 bucketEndTimeNs - updateTimeNs);
813 ValidateDurationBucket(data.bucket_info(1), bucketEndTimeNs, dumpTimeNs,
814 dumpTimeNs - bucketEndTimeNs);
815
816 // Max duration of syncs per uid while uid holding WL.
817 StatsLogReport durationMaxPersistAfter = report.metrics(2);
818 EXPECT_EQ(durationMaxPersistAfter.metric_id(), durationMaxPersist.id());
819 EXPECT_TRUE(durationMaxPersistAfter.has_duration_metrics());
820 durationMetrics.Clear();
821 sortMetricDataByDimensionsValue(durationMaxPersistAfter.duration_metrics(), &durationMetrics);
822 ASSERT_EQ(durationMetrics.data_size(), 2);
823
824 // Uid 1. Duration = 48 in the later bucket.
825 data = durationMetrics.data(0);
826 ValidateAttributionUidDimension(data.dimensions_in_what(), util::SYNC_STATE_CHANGED, app1Uid);
827 ASSERT_EQ(data.bucket_info_size(), 1);
828 ValidateDurationBucket(data.bucket_info(0), bucketEndTimeNs, dumpTimeNs, 48 * NS_PER_SEC);
829
830 // Uid 3. Duration = 25.
831 data = durationMetrics.data(1);
832 ValidateAttributionUidDimension(data.dimensions_in_what(), util::SYNC_STATE_CHANGED, app3Uid);
833 ASSERT_EQ(data.bucket_info_size(), 1);
834 ValidateDurationBucket(data.bucket_info(0), updateTimeNs, bucketEndTimeNs, 25 * NS_PER_SEC);
835
836 // Duration of syncs per uid while uid holding WL, slice screen.
837 StatsLogReport durationSumPersistAfter = report.metrics(3);
838 EXPECT_EQ(durationSumPersistAfter.metric_id(), durationSumPersist.id());
839 EXPECT_TRUE(durationSumPersistAfter.has_duration_metrics());
840 durationMetrics.Clear();
841 sortMetricDataByDimensionsValue(durationSumPersistAfter.duration_metrics(), &durationMetrics);
842 ASSERT_EQ(durationMetrics.data_size(), 4);
843
844 // Uid 1 in BG. Duration = 15.
845 data = durationMetrics.data(0);
846 ValidateAttributionUidDimension(data.dimensions_in_what(), util::SYNC_STATE_CHANGED, app1Uid);
847 ValidateStateValue(data.slice_by_state(), util::UID_PROCESS_STATE_CHANGED,
848 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND);
849 ASSERT_EQ(data.bucket_info_size(), 1);
850 ValidateDurationBucket(data.bucket_info(0), updateTimeNs, bucketEndTimeNs, 15 * NS_PER_SEC);
851
852 // Uid 2 in FG. Duration = bucketSize - 70 in first bucket, 10 in second bucket.
853 data = durationMetrics.data(1);
854 ValidateAttributionUidDimension(data.dimensions_in_what(), util::SYNC_STATE_CHANGED, app2Uid);
855 ValidateStateValue(data.slice_by_state(), util::UID_PROCESS_STATE_CHANGED,
856 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND);
857 ASSERT_EQ(data.bucket_info_size(), 2);
858 ValidateDurationBucket(data.bucket_info(0), updateTimeNs, bucketEndTimeNs,
859 bucketSizeNs - 70 * NS_PER_SEC);
860 ValidateDurationBucket(data.bucket_info(1), bucketEndTimeNs, dumpTimeNs, 10 * NS_PER_SEC);
861
862 // Uid 3 in FG. Duration = 5.
863 data = durationMetrics.data(2);
864 ValidateAttributionUidDimension(data.dimensions_in_what(), util::SYNC_STATE_CHANGED, app3Uid);
865 ValidateStateValue(data.slice_by_state(), util::UID_PROCESS_STATE_CHANGED,
866 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND);
867 ASSERT_EQ(data.bucket_info_size(), 1);
868 ValidateDurationBucket(data.bucket_info(0), updateTimeNs, bucketEndTimeNs, 5 * NS_PER_SEC);
869
870 // Uid 3 in BG. Duration = 20.
871 data = durationMetrics.data(3);
872 ValidateAttributionUidDimension(data.dimensions_in_what(), util::SYNC_STATE_CHANGED, app3Uid);
873 ValidateStateValue(data.slice_by_state(), util::UID_PROCESS_STATE_CHANGED,
874 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND);
875 ASSERT_EQ(data.bucket_info_size(), 1);
876 ValidateDurationBucket(data.bucket_info(0), updateTimeNs, bucketEndTimeNs, 20 * NS_PER_SEC);
877 }
878
TEST_F(ConfigUpdateE2eTest,TestGaugeMetric)879 TEST_F(ConfigUpdateE2eTest, TestGaugeMetric) {
880 StatsdConfig config;
881 config.add_allowed_log_source("AID_ROOT");
882 config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
883
884 AtomMatcher appStartMatcher = CreateSimpleAtomMatcher("AppStart", util::APP_START_OCCURRED);
885 *config.add_atom_matcher() = appStartMatcher;
886 AtomMatcher backgroundMatcher = CreateMoveToBackgroundAtomMatcher();
887 *config.add_atom_matcher() = backgroundMatcher;
888 AtomMatcher foregroundMatcher = CreateMoveToForegroundAtomMatcher();
889 *config.add_atom_matcher() = foregroundMatcher;
890 AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
891 *config.add_atom_matcher() = screenOnMatcher;
892 AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
893 *config.add_atom_matcher() = screenOffMatcher;
894 AtomMatcher subsystemSleepMatcher =
895 CreateSimpleAtomMatcher("SubsystemSleep", util::SUBSYSTEM_SLEEP_STATE);
896 *config.add_atom_matcher() = subsystemSleepMatcher;
897
898 Predicate isInBackgroundPredicate = CreateIsInBackgroundPredicate();
899 *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
900 CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /*uid field*/});
901 *config.add_predicate() = isInBackgroundPredicate;
902
903 Predicate screenOnPredicate = CreateScreenIsOnPredicate();
904 *config.add_predicate() = screenOnPredicate;
905
906 GaugeMetric gaugePullPersist =
907 createGaugeMetric("SubsystemSleepWhileScreenOn", subsystemSleepMatcher.id(),
908 GaugeMetric::RANDOM_ONE_SAMPLE, screenOnPredicate.id(), {});
909 *gaugePullPersist.mutable_dimensions_in_what() =
910 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
911
912 GaugeMetric gaugePushPersist =
913 createGaugeMetric("AppStartWhileInBg", appStartMatcher.id(),
914 GaugeMetric::FIRST_N_SAMPLES, isInBackgroundPredicate.id(), nullopt);
915 *gaugePushPersist.mutable_dimensions_in_what() =
916 CreateDimensions(util::APP_START_OCCURRED, {1 /*uid field*/});
917 // Links between sync state atom and condition of uid is holding wakelock.
918 MetricConditionLink* links = gaugePushPersist.add_links();
919 links->set_condition(isInBackgroundPredicate.id());
920 *links->mutable_fields_in_what() =
921 CreateDimensions(util::APP_START_OCCURRED, {1 /*uid field*/});
922 *links->mutable_fields_in_condition() =
923 CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /*uid field*/});
924
925 GaugeMetric gaugeChange = createGaugeMetric("GaugeScrOn", screenOnMatcher.id(),
926 GaugeMetric::RANDOM_ONE_SAMPLE, nullopt, nullopt);
927 GaugeMetric gaugeRemove =
928 createGaugeMetric("GaugeSubsysTriggerScr", subsystemSleepMatcher.id(),
929 GaugeMetric::FIRST_N_SAMPLES, nullopt, screenOnMatcher.id());
930 *gaugeRemove.mutable_dimensions_in_what() =
931 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
932 *config.add_gauge_metric() = gaugeRemove;
933 *config.add_gauge_metric() = gaugePullPersist;
934 *config.add_gauge_metric() = gaugeChange;
935 *config.add_gauge_metric() = gaugePushPersist;
936
937 ConfigKey key(123, 987);
938 uint64_t bucketStartTimeNs = getElapsedRealtimeNs(); // 0:10
939 uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(TEN_MINUTES) * 1000000LL;
940 sp<StatsLogProcessor> processor = CreateStatsLogProcessor(
941 bucketStartTimeNs, bucketStartTimeNs, config, key,
942 SharedRefBase::make<FakeSubsystemSleepCallback>(), util::SUBSYSTEM_SLEEP_STATE);
943
944 int app1Uid = 123, app2Uid = 456;
945
946 // Initialize log events before update.
947 std::vector<std::unique_ptr<LogEvent>> events;
948 events.push_back(CreateMoveToBackgroundEvent(bucketStartTimeNs + 5 * NS_PER_SEC, app1Uid));
949 events.push_back(CreateAppStartOccurredEvent(bucketStartTimeNs + 10 * NS_PER_SEC, app1Uid,
950 "app1", AppStartOccurred::WARM, "", "", true,
951 /*start_msec*/ 101)); // Kept by gaugePushPersist.
952 events.push_back(
953 CreateAppStartOccurredEvent(bucketStartTimeNs + 15 * NS_PER_SEC, app2Uid, "app2",
954 AppStartOccurred::WARM, "", "", true,
955 /*start_msec*/ 201)); // Not kept by gaugePushPersist.
956 events.push_back(CreateScreenStateChangedEvent(
957 bucketStartTimeNs + 20 * NS_PER_SEC,
958 android::view::DISPLAY_STATE_ON)); // Pulls gaugePullPersist and gaugeRemove.
959 events.push_back(CreateMoveToBackgroundEvent(bucketStartTimeNs + 25 * NS_PER_SEC, app2Uid));
960 events.push_back(
961 CreateScreenStateChangedEvent(bucketStartTimeNs + 30 * NS_PER_SEC,
962 android::view::DisplayStateEnum::DISPLAY_STATE_OFF));
963 events.push_back(CreateAppStartOccurredEvent(bucketStartTimeNs + 35 * NS_PER_SEC, app1Uid,
964 "app1", AppStartOccurred::WARM, "", "", true,
965 /*start_msec*/ 102)); // Kept by gaugePushPersist.
966 events.push_back(CreateAppStartOccurredEvent(bucketStartTimeNs + 40 * NS_PER_SEC, app2Uid,
967 "app2", AppStartOccurred::WARM, "", "", true,
968 /*start_msec*/ 202)); // Kept by gaugePushPersist.
969 events.push_back(CreateScreenStateChangedEvent(
970 bucketStartTimeNs + 45 * NS_PER_SEC,
971 android::view::DisplayStateEnum::DISPLAY_STATE_ON)); // Pulls gaugeRemove only.
972 events.push_back(CreateMoveToForegroundEvent(bucketStartTimeNs + 50 * NS_PER_SEC, app1Uid));
973
974 // Send log events to StatsLogProcessor.
975 for (auto& event : events) {
976 processor->mPullerManager->ForceClearPullerCache();
977 processor->OnLogEvent(event.get());
978 }
979 processor->mPullerManager->ForceClearPullerCache();
980
981 // Do the update. Add matchers/conditions in different order to force indices to change.
982 StatsdConfig newConfig;
983 newConfig.add_allowed_log_source("AID_ROOT");
984 newConfig.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
985
986 *newConfig.add_atom_matcher() = screenOffMatcher;
987 *newConfig.add_atom_matcher() = foregroundMatcher;
988 *newConfig.add_atom_matcher() = appStartMatcher;
989 *newConfig.add_atom_matcher() = subsystemSleepMatcher;
990 *newConfig.add_atom_matcher() = backgroundMatcher;
991 *newConfig.add_atom_matcher() = screenOnMatcher;
992
993 *newConfig.add_predicate() = isInBackgroundPredicate;
994 *newConfig.add_predicate() = screenOnPredicate;
995
996 gaugeChange.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES);
997 *newConfig.add_gauge_metric() = gaugeChange;
998 GaugeMetric gaugeNew = createGaugeMetric("GaugeSubsys", subsystemSleepMatcher.id(),
999 GaugeMetric::RANDOM_ONE_SAMPLE, {}, {});
1000 *gaugeNew.mutable_dimensions_in_what() =
1001 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
1002 *newConfig.add_gauge_metric() = gaugeNew;
1003 *newConfig.add_gauge_metric() = gaugePushPersist;
1004 *newConfig.add_gauge_metric() = gaugePullPersist;
1005
1006 int64_t updateTimeNs = bucketStartTimeNs + 60 * NS_PER_SEC;
1007 // Update pulls gaugePullPersist and gaugeNew.
1008 processor->OnConfigUpdated(updateTimeNs, key, newConfig);
1009
1010 // Verify puller manager is properly set.
1011 sp<StatsPullerManager> pullerManager = processor->mPullerManager;
1012 EXPECT_EQ(pullerManager->mNextPullTimeNs, bucketStartTimeNs + bucketSizeNs);
1013 ASSERT_EQ(pullerManager->mReceivers.size(), 1);
1014 ASSERT_EQ(pullerManager->mReceivers.begin()->second.size(), 2);
1015
1016 // Send events after the update. Counts reset to 0 since this is a new bucket.
1017 events.clear();
1018 events.push_back(
1019 CreateAppStartOccurredEvent(bucketStartTimeNs + 65 * NS_PER_SEC, app1Uid, "app1",
1020 AppStartOccurred::WARM, "", "", true,
1021 /*start_msec*/ 103)); // Not kept by gaugePushPersist.
1022 events.push_back(CreateAppStartOccurredEvent(bucketStartTimeNs + 70 * NS_PER_SEC, app2Uid,
1023 "app2", AppStartOccurred::WARM, "", "", true,
1024 /*start_msec*/ 203)); // Kept by gaugePushPersist.
1025 events.push_back(
1026 CreateScreenStateChangedEvent(bucketStartTimeNs + 75 * NS_PER_SEC,
1027 android::view::DisplayStateEnum::DISPLAY_STATE_OFF));
1028 events.push_back(
1029 CreateScreenStateChangedEvent(bucketStartTimeNs + 80 * NS_PER_SEC,
1030 android::view::DisplayStateEnum::DISPLAY_STATE_ON));
1031 events.push_back(CreateMoveToBackgroundEvent(bucketStartTimeNs + 85 * NS_PER_SEC, app1Uid));
1032 events.push_back(
1033 CreateScreenStateChangedEvent(bucketStartTimeNs + 90 * NS_PER_SEC,
1034 android::view::DisplayStateEnum::DISPLAY_STATE_OFF));
1035 events.push_back(CreateAppStartOccurredEvent(bucketStartTimeNs + 95 * NS_PER_SEC, app1Uid,
1036 "app1", AppStartOccurred::WARM, "", "", true,
1037 /*start_msec*/ 104)); // Kept by gaugePushPersist.
1038 events.push_back(CreateAppStartOccurredEvent(bucketStartTimeNs + 100 * NS_PER_SEC, app2Uid,
1039 "app2", AppStartOccurred::WARM, "", "", true,
1040 /*start_msec*/ 204)); // Kept by gaugePushPersist.
1041 events.push_back(
1042 CreateScreenStateChangedEvent(bucketStartTimeNs + 105 * NS_PER_SEC,
1043 android::view::DisplayStateEnum::DISPLAY_STATE_ON));
1044 events.push_back(
1045 CreateScreenStateChangedEvent(bucketStartTimeNs + 110 * NS_PER_SEC,
1046 android::view::DisplayStateEnum::DISPLAY_STATE_OFF));
1047 // Send log events to StatsLogProcessor.
1048 for (auto& event : events) {
1049 processor->mPullerManager->ForceClearPullerCache();
1050 processor->OnLogEvent(event.get());
1051 }
1052 processor->mPullerManager->ForceClearPullerCache();
1053 // Pulling alarm arrive, triggering a bucket split. Only gaugeNew keeps the data since the
1054 // condition is false for gaugeNew.
1055 processor->informPullAlarmFired(bucketStartTimeNs + bucketSizeNs);
1056
1057 uint64_t dumpTimeNs = bucketStartTimeNs + bucketSizeNs + 10 * NS_PER_SEC;
1058 ConfigMetricsReportList reports;
1059 vector<uint8_t> buffer;
1060 processor->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, FAST, &buffer);
1061 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1062 backfillDimensionPath(&reports);
1063 backfillStringInReport(&reports);
1064 backfillStartEndTimestamp(&reports);
1065 ASSERT_EQ(reports.reports_size(), 2);
1066
1067 int64_t roundedBucketStartNs = MillisToNano(NanoToMillis(bucketStartTimeNs));
1068 int64_t roundedUpdateTimeNs = MillisToNano(NanoToMillis(updateTimeNs));
1069 int64_t roundedBucketEndNs = MillisToNano(NanoToMillis(bucketStartTimeNs + bucketSizeNs));
1070 int64_t roundedDumpTimeNs = MillisToNano(NanoToMillis(dumpTimeNs));
1071
1072 // Report from before update.
1073 ConfigMetricsReport report = reports.reports(0);
1074 ASSERT_EQ(report.metrics_size(), 4);
1075 // Gauge subsystem sleep state trigger screen on. 2 pulls occurred.
1076 StatsLogReport gaugeRemoveBefore = report.metrics(0);
1077 EXPECT_EQ(gaugeRemoveBefore.metric_id(), gaugeRemove.id());
1078 EXPECT_TRUE(gaugeRemoveBefore.has_gauge_metrics());
1079 StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
1080 sortMetricDataByDimensionsValue(gaugeRemoveBefore.gauge_metrics(), &gaugeMetrics);
1081 ASSERT_EQ(gaugeMetrics.data_size(), 2);
1082 auto data = gaugeMetrics.data(0);
1083 ValidateSubsystemSleepDimension(data.dimensions_in_what(), "subsystem_name_1");
1084 ASSERT_EQ(data.bucket_info_size(), 1);
1085 ValidateGaugeBucketTimes(data.bucket_info(0), roundedBucketStartNs, roundedUpdateTimeNs,
1086 {(int64_t)(bucketStartTimeNs + 20 * NS_PER_SEC),
1087 (int64_t)(bucketStartTimeNs + 45 * NS_PER_SEC)});
1088 ASSERT_EQ(data.bucket_info(0).atom_size(), 2);
1089 EXPECT_EQ(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 101);
1090 EXPECT_EQ(data.bucket_info(0).atom(1).subsystem_sleep_state().time_millis(), 401);
1091
1092 data = gaugeMetrics.data(1);
1093 ValidateSubsystemSleepDimension(data.dimensions_in_what(), "subsystem_name_2");
1094 ASSERT_EQ(data.bucket_info_size(), 1);
1095 ValidateGaugeBucketTimes(data.bucket_info(0), roundedBucketStartNs, roundedUpdateTimeNs,
1096 {(int64_t)(bucketStartTimeNs + 20 * NS_PER_SEC),
1097 (int64_t)(bucketStartTimeNs + 45 * NS_PER_SEC)});
1098 ASSERT_EQ(data.bucket_info(0).atom_size(), 2);
1099 EXPECT_EQ(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 102);
1100 EXPECT_EQ(data.bucket_info(0).atom(1).subsystem_sleep_state().time_millis(), 402);
1101
1102 // Gauge subsystem sleep state when screen is on. One pull when the screen turned on
1103 StatsLogReport gaugePullPersistBefore = report.metrics(1);
1104 EXPECT_EQ(gaugePullPersistBefore.metric_id(), gaugePullPersist.id());
1105 EXPECT_TRUE(gaugePullPersistBefore.has_gauge_metrics());
1106 gaugeMetrics.Clear();
1107 sortMetricDataByDimensionsValue(gaugePullPersistBefore.gauge_metrics(), &gaugeMetrics);
1108 ASSERT_EQ(gaugeMetrics.data_size(), 2);
1109 data = gaugeMetrics.data(0);
1110 ValidateSubsystemSleepDimension(data.dimensions_in_what(), "subsystem_name_1");
1111 ASSERT_EQ(data.bucket_info_size(), 1);
1112 ValidateGaugeBucketTimes(data.bucket_info(0), roundedBucketStartNs, roundedUpdateTimeNs,
1113 {(int64_t)(bucketStartTimeNs + 20 * NS_PER_SEC)});
1114 ASSERT_EQ(data.bucket_info(0).atom_size(), 1);
1115 EXPECT_EQ(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 101);
1116
1117 data = gaugeMetrics.data(1);
1118 ValidateSubsystemSleepDimension(data.dimensions_in_what(), "subsystem_name_2");
1119 ASSERT_EQ(data.bucket_info_size(), 1);
1120 ValidateGaugeBucketTimes(data.bucket_info(0), roundedBucketStartNs, roundedUpdateTimeNs,
1121 {(int64_t)(bucketStartTimeNs + 20 * NS_PER_SEC)});
1122 ASSERT_EQ(data.bucket_info(0).atom_size(), 1);
1123 EXPECT_EQ(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 102);
1124
1125 // Gauge screen on events, one per bucket.
1126 StatsLogReport gaugeChangeBefore = report.metrics(2);
1127 EXPECT_EQ(gaugeChangeBefore.metric_id(), gaugeChange.id());
1128 EXPECT_TRUE(gaugeChangeBefore.has_gauge_metrics());
1129 gaugeMetrics.Clear();
1130 sortMetricDataByDimensionsValue(gaugeChangeBefore.gauge_metrics(), &gaugeMetrics);
1131 ASSERT_EQ(gaugeMetrics.data_size(), 1);
1132 data = gaugeMetrics.data(0);
1133 ASSERT_EQ(data.bucket_info_size(), 1);
1134 ValidateGaugeBucketTimes(data.bucket_info(0), roundedBucketStartNs, roundedUpdateTimeNs,
1135 {(int64_t)(bucketStartTimeNs + 20 * NS_PER_SEC)});
1136 ASSERT_EQ(data.bucket_info(0).atom_size(), 1);
1137 EXPECT_EQ(data.bucket_info(0).atom(0).screen_state_changed().state(),
1138 android::view::DISPLAY_STATE_ON);
1139
1140 // Gauge app start while app is in the background. App 1 started twice, app 2 started once.
1141 StatsLogReport gaugePushPersistBefore = report.metrics(3);
1142 EXPECT_EQ(gaugePushPersistBefore.metric_id(), gaugePushPersist.id());
1143 EXPECT_TRUE(gaugePushPersistBefore.has_gauge_metrics());
1144 gaugeMetrics.Clear();
1145 sortMetricDataByDimensionsValue(gaugePushPersistBefore.gauge_metrics(), &gaugeMetrics);
1146 ASSERT_EQ(gaugeMetrics.data_size(), 2);
1147 data = gaugeMetrics.data(0);
1148 ValidateUidDimension(data.dimensions_in_what(), util::APP_START_OCCURRED, app1Uid);
1149 ASSERT_EQ(data.bucket_info_size(), 1);
1150 ValidateGaugeBucketTimes(data.bucket_info(0), roundedBucketStartNs, roundedUpdateTimeNs,
1151 {(int64_t)(bucketStartTimeNs + 10 * NS_PER_SEC),
1152 (int64_t)(bucketStartTimeNs + 35 * NS_PER_SEC)});
1153 ASSERT_EQ(data.bucket_info(0).atom_size(), 2);
1154 EXPECT_EQ(data.bucket_info(0).atom(0).app_start_occurred().pkg_name(), "app1");
1155 EXPECT_EQ(data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis(), 101);
1156 EXPECT_EQ(data.bucket_info(0).atom(1).app_start_occurred().pkg_name(), "app1");
1157 EXPECT_EQ(data.bucket_info(0).atom(1).app_start_occurred().activity_start_millis(), 102);
1158
1159 data = gaugeMetrics.data(1);
1160 ValidateUidDimension(data.dimensions_in_what(), util::APP_START_OCCURRED, app2Uid);
1161 ASSERT_EQ(data.bucket_info_size(), 1);
1162 ValidateGaugeBucketTimes(data.bucket_info(0), roundedBucketStartNs, roundedUpdateTimeNs,
1163 {(int64_t)(bucketStartTimeNs + 40 * NS_PER_SEC)});
1164 ASSERT_EQ(data.bucket_info(0).atom_size(), 1);
1165 EXPECT_EQ(data.bucket_info(0).atom(0).app_start_occurred().pkg_name(), "app2");
1166 EXPECT_EQ(data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis(), 202);
1167
1168 // Report from after update.
1169 report = reports.reports(1);
1170 ASSERT_EQ(report.metrics_size(), 4);
1171 // Gauge screen on events FIRST_N_SAMPLES. There were 2.
1172 StatsLogReport gaugeChangeAfter = report.metrics(0);
1173 EXPECT_EQ(gaugeChangeAfter.metric_id(), gaugeChange.id());
1174 EXPECT_TRUE(gaugeChangeAfter.has_gauge_metrics());
1175 gaugeMetrics.Clear();
1176 sortMetricDataByDimensionsValue(gaugeChangeAfter.gauge_metrics(), &gaugeMetrics);
1177 ASSERT_EQ(gaugeMetrics.data_size(), 1);
1178 data = gaugeMetrics.data(0);
1179 ASSERT_EQ(data.bucket_info_size(), 1);
1180 ValidateGaugeBucketTimes(data.bucket_info(0), roundedUpdateTimeNs, roundedBucketEndNs,
1181 {(int64_t)(bucketStartTimeNs + 80 * NS_PER_SEC),
1182 (int64_t)(bucketStartTimeNs + 105 * NS_PER_SEC)});
1183 ASSERT_EQ(data.bucket_info(0).atom_size(), 2);
1184 EXPECT_EQ(data.bucket_info(0).atom(0).screen_state_changed().state(),
1185 android::view::DISPLAY_STATE_ON);
1186 EXPECT_EQ(data.bucket_info(0).atom(1).screen_state_changed().state(),
1187 android::view::DISPLAY_STATE_ON);
1188
1189 // Gauge subsystem sleep state, random one sample, no condition.
1190 // Pulled at update time and after the normal bucket end.
1191 StatsLogReport gaugeNewAfter = report.metrics(1);
1192 EXPECT_EQ(gaugeNewAfter.metric_id(), gaugeNew.id());
1193 EXPECT_TRUE(gaugeNewAfter.has_gauge_metrics());
1194 gaugeMetrics.Clear();
1195 sortMetricDataByDimensionsValue(gaugeNewAfter.gauge_metrics(), &gaugeMetrics);
1196 ASSERT_EQ(gaugeMetrics.data_size(), 2);
1197 data = gaugeMetrics.data(0);
1198 ValidateSubsystemSleepDimension(data.dimensions_in_what(), "subsystem_name_1");
1199 ASSERT_EQ(data.bucket_info_size(), 2);
1200 ValidateGaugeBucketTimes(data.bucket_info(0), roundedUpdateTimeNs, roundedBucketEndNs,
1201 {updateTimeNs});
1202 ASSERT_EQ(data.bucket_info(0).atom_size(), 1);
1203 EXPECT_EQ(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 901);
1204 ValidateGaugeBucketTimes(data.bucket_info(1), roundedBucketEndNs, roundedDumpTimeNs,
1205 {(int64_t)(bucketStartTimeNs + bucketSizeNs)});
1206 ASSERT_EQ(data.bucket_info(1).atom_size(), 1);
1207 EXPECT_EQ(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 1601);
1208
1209 data = gaugeMetrics.data(1);
1210 ValidateSubsystemSleepDimension(data.dimensions_in_what(), "subsystem_name_2");
1211 ASSERT_EQ(data.bucket_info_size(), 2);
1212 ValidateGaugeBucketTimes(data.bucket_info(0), roundedUpdateTimeNs, roundedBucketEndNs,
1213 {updateTimeNs});
1214 ASSERT_EQ(data.bucket_info(0).atom_size(), 1);
1215 EXPECT_EQ(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 902);
1216 ValidateGaugeBucketTimes(data.bucket_info(1), roundedBucketEndNs, roundedDumpTimeNs,
1217 {(int64_t)(bucketStartTimeNs + bucketSizeNs)});
1218 ASSERT_EQ(data.bucket_info(1).atom_size(), 1);
1219 EXPECT_EQ(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 1602);
1220
1221 // Gauge app start while app is in the background. App 1 started once, app 2 started twice.
1222 StatsLogReport gaugePushPersistAfter = report.metrics(2);
1223 EXPECT_EQ(gaugePushPersistAfter.metric_id(), gaugePushPersist.id());
1224 EXPECT_TRUE(gaugePushPersistAfter.has_gauge_metrics());
1225 gaugeMetrics.Clear();
1226 sortMetricDataByDimensionsValue(gaugePushPersistAfter.gauge_metrics(), &gaugeMetrics);
1227 ASSERT_EQ(gaugeMetrics.data_size(), 2);
1228 data = gaugeMetrics.data(0);
1229 ValidateUidDimension(data.dimensions_in_what(), util::APP_START_OCCURRED, app1Uid);
1230 ASSERT_EQ(data.bucket_info_size(), 1);
1231 ValidateGaugeBucketTimes(data.bucket_info(0), roundedUpdateTimeNs, roundedBucketEndNs,
1232 {(int64_t)(bucketStartTimeNs + 95 * NS_PER_SEC)});
1233 ASSERT_EQ(data.bucket_info(0).atom_size(), 1);
1234 EXPECT_EQ(data.bucket_info(0).atom(0).app_start_occurred().pkg_name(), "app1");
1235 EXPECT_EQ(data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis(), 104);
1236
1237 data = gaugeMetrics.data(1);
1238 ValidateUidDimension(data.dimensions_in_what(), util::APP_START_OCCURRED, app2Uid);
1239 ASSERT_EQ(data.bucket_info_size(), 1);
1240 ValidateGaugeBucketTimes(data.bucket_info(0), roundedUpdateTimeNs, roundedBucketEndNs,
1241 {(int64_t)(bucketStartTimeNs + 70 * NS_PER_SEC),
1242 (int64_t)(bucketStartTimeNs + 100 * NS_PER_SEC)});
1243 ASSERT_EQ(data.bucket_info(0).atom_size(), 2);
1244 EXPECT_EQ(data.bucket_info(0).atom(0).app_start_occurred().pkg_name(), "app2");
1245 EXPECT_EQ(data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis(), 203);
1246 EXPECT_EQ(data.bucket_info(0).atom(1).app_start_occurred().pkg_name(), "app2");
1247 EXPECT_EQ(data.bucket_info(0).atom(1).app_start_occurred().activity_start_millis(), 204);
1248
1249 // Gauge subsystem sleep state when screen is on. One pull at update since screen is on then.
1250 StatsLogReport gaugePullPersistAfter = report.metrics(3);
1251 EXPECT_EQ(gaugePullPersistAfter.metric_id(), gaugePullPersist.id());
1252 EXPECT_TRUE(gaugePullPersistAfter.has_gauge_metrics());
1253 gaugeMetrics.Clear();
1254 sortMetricDataByDimensionsValue(gaugePullPersistAfter.gauge_metrics(), &gaugeMetrics);
1255 ASSERT_EQ(gaugeMetrics.data_size(), 2);
1256 data = gaugeMetrics.data(0);
1257 ValidateSubsystemSleepDimension(data.dimensions_in_what(), "subsystem_name_1");
1258 ASSERT_EQ(data.bucket_info_size(), 1);
1259 ValidateGaugeBucketTimes(data.bucket_info(0), roundedUpdateTimeNs, roundedBucketEndNs,
1260 {updateTimeNs});
1261 ASSERT_EQ(data.bucket_info(0).atom_size(), 1);
1262 EXPECT_EQ(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 901);
1263
1264 data = gaugeMetrics.data(1);
1265 ValidateSubsystemSleepDimension(data.dimensions_in_what(), "subsystem_name_2");
1266 ASSERT_EQ(data.bucket_info_size(), 1);
1267 ValidateGaugeBucketTimes(data.bucket_info(0), roundedUpdateTimeNs, roundedBucketEndNs,
1268 {updateTimeNs});
1269 ASSERT_EQ(data.bucket_info(0).atom_size(), 1);
1270 EXPECT_EQ(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 902);
1271 }
1272
TEST_F(ConfigUpdateE2eTest,TestValueMetric)1273 TEST_F(ConfigUpdateE2eTest, TestValueMetric) {
1274 StatsdConfig config;
1275 config.add_allowed_log_source("AID_ROOT");
1276 config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
1277
1278 AtomMatcher brightnessMatcher = CreateScreenBrightnessChangedAtomMatcher();
1279 *config.add_atom_matcher() = brightnessMatcher;
1280 AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
1281 *config.add_atom_matcher() = screenOnMatcher;
1282 AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
1283 *config.add_atom_matcher() = screenOffMatcher;
1284 AtomMatcher batteryPluggedUsbMatcher = CreateBatteryStateUsbMatcher();
1285 *config.add_atom_matcher() = batteryPluggedUsbMatcher;
1286 AtomMatcher unpluggedMatcher = CreateBatteryStateNoneMatcher();
1287 *config.add_atom_matcher() = unpluggedMatcher;
1288 AtomMatcher subsystemSleepMatcher =
1289 CreateSimpleAtomMatcher("SubsystemSleep", util::SUBSYSTEM_SLEEP_STATE);
1290 *config.add_atom_matcher() = subsystemSleepMatcher;
1291
1292 Predicate screenOnPredicate = CreateScreenIsOnPredicate();
1293 *config.add_predicate() = screenOnPredicate;
1294 Predicate unpluggedPredicate = CreateDeviceUnpluggedPredicate();
1295 *config.add_predicate() = unpluggedPredicate;
1296
1297 State screenState = CreateScreenState();
1298 *config.add_state() = screenState;
1299
1300 ValueMetric valuePullPersist =
1301 createValueMetric("SubsystemSleepWhileUnpluggedSliceScreen", subsystemSleepMatcher, 4,
1302 unpluggedPredicate.id(), {screenState.id()});
1303 *valuePullPersist.mutable_dimensions_in_what() =
1304 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
1305
1306 ValueMetric valuePushPersist = createValueMetric(
1307 "MinScreenBrightnessWhileScreenOn", brightnessMatcher, 1, screenOnPredicate.id(), {});
1308 valuePushPersist.set_aggregation_type(ValueMetric::MIN);
1309
1310 ValueMetric valueChange =
1311 createValueMetric("SubsystemSleep", subsystemSleepMatcher, 4, nullopt, {});
1312 *valueChange.mutable_dimensions_in_what() =
1313 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
1314
1315 ValueMetric valueRemove =
1316 createValueMetric("AvgScreenBrightness", brightnessMatcher, 1, nullopt, {});
1317 valueRemove.set_aggregation_type(ValueMetric::AVG);
1318
1319 *config.add_value_metric() = valuePullPersist;
1320 *config.add_value_metric() = valueRemove;
1321 *config.add_value_metric() = valuePushPersist;
1322 *config.add_value_metric() = valueChange;
1323
1324 ConfigKey key(123, 987);
1325 uint64_t bucketStartTimeNs = getElapsedRealtimeNs();
1326 uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(TEN_MINUTES) * 1000000LL;
1327 // Config creation triggers pull #1.
1328 sp<StatsLogProcessor> processor = CreateStatsLogProcessor(
1329 bucketStartTimeNs, bucketStartTimeNs, config, key,
1330 SharedRefBase::make<FakeSubsystemSleepCallback>(), util::SUBSYSTEM_SLEEP_STATE);
1331
1332 // Initialize log events before update.
1333 // ValuePushPersist and ValuePullPersist will skip the bucket due to condition unknown.
1334 std::vector<std::unique_ptr<LogEvent>> events;
1335 events.push_back(CreateScreenBrightnessChangedEvent(bucketStartTimeNs + 5 * NS_PER_SEC, 5));
1336 events.push_back(CreateScreenStateChangedEvent(bucketStartTimeNs + 10 * NS_PER_SEC,
1337 android::view::DISPLAY_STATE_ON));
1338 events.push_back(CreateScreenBrightnessChangedEvent(bucketStartTimeNs + 15 * NS_PER_SEC, 15));
1339 events.push_back(CreateBatteryStateChangedEvent(
1340 bucketStartTimeNs + 20 * NS_PER_SEC,
1341 BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE)); // Pull #2.
1342 events.push_back(CreateScreenBrightnessChangedEvent(bucketStartTimeNs + 25 * NS_PER_SEC, 40));
1343
1344 // Send log events to StatsLogProcessor.
1345 for (auto& event : events) {
1346 processor->mPullerManager->ForceClearPullerCache();
1347 processor->OnLogEvent(event.get());
1348 }
1349 processor->mPullerManager->ForceClearPullerCache();
1350
1351 // Do the update. Add matchers/conditions in different order to force indices to change.
1352 StatsdConfig newConfig;
1353 newConfig.add_allowed_log_source("AID_ROOT");
1354 newConfig.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
1355
1356 *newConfig.add_atom_matcher() = screenOffMatcher;
1357 *newConfig.add_atom_matcher() = unpluggedMatcher;
1358 *newConfig.add_atom_matcher() = batteryPluggedUsbMatcher;
1359 *newConfig.add_atom_matcher() = subsystemSleepMatcher;
1360 *newConfig.add_atom_matcher() = brightnessMatcher;
1361 *newConfig.add_atom_matcher() = screenOnMatcher;
1362
1363 *newConfig.add_predicate() = unpluggedPredicate;
1364 *newConfig.add_predicate() = screenOnPredicate;
1365
1366 *config.add_state() = screenState;
1367
1368 valueChange.set_condition(screenOnPredicate.id());
1369 *newConfig.add_value_metric() = valueChange;
1370 ValueMetric valueNew = createValueMetric("MaxScrBrightness", brightnessMatcher, 1, nullopt, {});
1371 valueNew.set_aggregation_type(ValueMetric::MAX);
1372 *newConfig.add_value_metric() = valueNew;
1373 *newConfig.add_value_metric() = valuePushPersist;
1374 *newConfig.add_value_metric() = valuePullPersist;
1375
1376 int64_t updateTimeNs = bucketStartTimeNs + 30 * NS_PER_SEC;
1377 // Update pulls valuePullPersist and valueNew. Pull #3.
1378 processor->OnConfigUpdated(updateTimeNs, key, newConfig);
1379
1380 // Verify puller manager is properly set.
1381 sp<StatsPullerManager> pullerManager = processor->mPullerManager;
1382 EXPECT_EQ(pullerManager->mNextPullTimeNs, bucketStartTimeNs + bucketSizeNs);
1383 ASSERT_EQ(pullerManager->mReceivers.size(), 1);
1384 ASSERT_EQ(pullerManager->mReceivers.begin()->second.size(), 2);
1385
1386 // Send events after the update. Values reset since this is a new bucket.
1387 events.clear();
1388 events.push_back(CreateScreenBrightnessChangedEvent(bucketStartTimeNs + 35 * NS_PER_SEC, 30));
1389 events.push_back(CreateScreenStateChangedEvent(bucketStartTimeNs + 40 * NS_PER_SEC,
1390 android::view::DISPLAY_STATE_OFF)); // Pull #4.
1391 events.push_back(CreateScreenBrightnessChangedEvent(bucketStartTimeNs + 45 * NS_PER_SEC, 20));
1392 events.push_back(CreateBatteryStateChangedEvent(
1393 bucketStartTimeNs + 50 * NS_PER_SEC,
1394 BatteryPluggedStateEnum::BATTERY_PLUGGED_USB)); // Pull #5.
1395 events.push_back(CreateScreenBrightnessChangedEvent(bucketStartTimeNs + 55 * NS_PER_SEC, 25));
1396 events.push_back(CreateScreenStateChangedEvent(bucketStartTimeNs + 60 * NS_PER_SEC,
1397 android::view::DISPLAY_STATE_ON)); // Pull #6.
1398 events.push_back(CreateBatteryStateChangedEvent(
1399 bucketStartTimeNs + 65 * NS_PER_SEC,
1400 BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE)); // Pull #7.
1401 events.push_back(CreateScreenBrightnessChangedEvent(bucketStartTimeNs + 70 * NS_PER_SEC, 40));
1402
1403 // Send log events to StatsLogProcessor.
1404 for (auto& event : events) {
1405 processor->mPullerManager->ForceClearPullerCache();
1406 processor->OnLogEvent(event.get());
1407 }
1408 processor->mPullerManager->ForceClearPullerCache();
1409
1410 // Pulling alarm arrive, triggering a bucket split.
1411 // Both valuePullPersist and valueChange use the value since both conditions are true. Pull #8.
1412 processor->informPullAlarmFired(bucketStartTimeNs + bucketSizeNs);
1413 processor->OnLogEvent(CreateScreenBrightnessChangedEvent(
1414 bucketStartTimeNs + bucketSizeNs + 5 * NS_PER_SEC, 50)
1415 .get());
1416
1417 uint64_t dumpTimeNs = bucketStartTimeNs + bucketSizeNs + 10 * NS_PER_SEC;
1418 ConfigMetricsReportList reports;
1419 vector<uint8_t> buffer;
1420 processor->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, FAST, &buffer);
1421 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1422 backfillDimensionPath(&reports);
1423 backfillStringInReport(&reports);
1424 backfillStartEndTimestamp(&reports);
1425 ASSERT_EQ(reports.reports_size(), 2);
1426
1427 int64_t roundedBucketStartNs = MillisToNano(NanoToMillis(bucketStartTimeNs));
1428 int64_t roundedUpdateTimeNs = MillisToNano(NanoToMillis(updateTimeNs));
1429 int64_t roundedBucketEndNs = MillisToNano(NanoToMillis(bucketStartTimeNs + bucketSizeNs));
1430 int64_t roundedDumpTimeNs = MillisToNano(NanoToMillis(dumpTimeNs));
1431
1432 // Report from before update.
1433 ConfigMetricsReport report = reports.reports(0);
1434 ASSERT_EQ(report.metrics_size(), 4);
1435 // Pull subsystem sleep while unplugged slice screen. Bucket skipped due to condition unknown.
1436 StatsLogReport valuePullPersistBefore = report.metrics(0);
1437 EXPECT_EQ(valuePullPersistBefore.metric_id(), valuePullPersist.id());
1438 EXPECT_TRUE(valuePullPersistBefore.has_value_metrics());
1439 ASSERT_EQ(valuePullPersistBefore.value_metrics().data_size(), 0);
1440 ASSERT_EQ(valuePullPersistBefore.value_metrics().skipped_size(), 1);
1441 StatsLogReport::SkippedBuckets skipBucket = valuePullPersistBefore.value_metrics().skipped(0);
1442 EXPECT_EQ(skipBucket.start_bucket_elapsed_nanos(), roundedBucketStartNs);
1443 EXPECT_EQ(skipBucket.end_bucket_elapsed_nanos(), roundedUpdateTimeNs);
1444 ASSERT_EQ(skipBucket.drop_event_size(), 1);
1445 EXPECT_EQ(skipBucket.drop_event(0).drop_reason(), BucketDropReason::CONDITION_UNKNOWN);
1446
1447 // Average screen brightness. Values were 5, 15, 40. Avg: 20.
1448 StatsLogReport valueRemoveBefore = report.metrics(1);
1449 EXPECT_EQ(valueRemoveBefore.metric_id(), valueRemove.id());
1450 EXPECT_TRUE(valueRemoveBefore.has_value_metrics());
1451 StatsLogReport::ValueMetricDataWrapper valueMetrics;
1452 sortMetricDataByDimensionsValue(valueRemoveBefore.value_metrics(), &valueMetrics);
1453 ASSERT_EQ(valueMetrics.data_size(), 1);
1454 ValueMetricData data = valueMetrics.data(0);
1455 EXPECT_FALSE(data.has_dimensions_in_what());
1456 EXPECT_EQ(data.slice_by_state_size(), 0);
1457 ASSERT_EQ(data.bucket_info_size(), 1);
1458 ValidateValueBucket(data.bucket_info(0), roundedBucketStartNs, roundedUpdateTimeNs, {20}, 0);
1459
1460 // Min screen brightness while screen on. Bucket skipped due to condition unknown.
1461 StatsLogReport valuePushPersistBefore = report.metrics(2);
1462 EXPECT_EQ(valuePushPersistBefore.metric_id(), valuePushPersist.id());
1463 EXPECT_TRUE(valuePushPersistBefore.has_value_metrics());
1464 ASSERT_EQ(valuePushPersistBefore.value_metrics().data_size(), 0);
1465 ASSERT_EQ(valuePushPersistBefore.value_metrics().skipped_size(), 1);
1466 skipBucket = valuePushPersistBefore.value_metrics().skipped(0);
1467 EXPECT_EQ(skipBucket.start_bucket_elapsed_nanos(), roundedBucketStartNs);
1468 EXPECT_EQ(skipBucket.end_bucket_elapsed_nanos(), roundedUpdateTimeNs);
1469 ASSERT_EQ(skipBucket.drop_event_size(), 1);
1470 EXPECT_EQ(skipBucket.drop_event(0).drop_reason(), BucketDropReason::CONDITION_UNKNOWN);
1471
1472 // Pull Subsystem sleep state. Value is Pull #3 (900) - Pull#1 (100).
1473 StatsLogReport valueChangeBefore = report.metrics(3);
1474 EXPECT_EQ(valueChangeBefore.metric_id(), valueChange.id());
1475 EXPECT_TRUE(valueChangeBefore.has_value_metrics());
1476 valueMetrics.Clear();
1477 sortMetricDataByDimensionsValue(valueChangeBefore.value_metrics(), &valueMetrics);
1478 ASSERT_EQ(valueMetrics.data_size(), 2);
1479 data = valueMetrics.data(0);
1480 ValidateSubsystemSleepDimension(data.dimensions_in_what(), "subsystem_name_1");
1481 ASSERT_EQ(data.bucket_info_size(), 1);
1482 ValidateValueBucket(data.bucket_info(0), roundedBucketStartNs, roundedUpdateTimeNs, {800}, 0);
1483 data = valueMetrics.data(1);
1484 ValidateSubsystemSleepDimension(data.dimensions_in_what(), "subsystem_name_2");
1485 ASSERT_EQ(data.bucket_info_size(), 1);
1486 ValidateValueBucket(data.bucket_info(0), roundedBucketStartNs, roundedUpdateTimeNs, {800}, 0);
1487
1488 // Report from after update.
1489 report = reports.reports(1);
1490 ASSERT_EQ(report.metrics_size(), 4);
1491 // Pull subsystem sleep while screen on.
1492 // Pull#4 (1600) - pull#3 (900) + pull#8 (6400) - pull#6 (3600)
1493 StatsLogReport valueChangeAfter = report.metrics(0);
1494 EXPECT_EQ(valueChangeAfter.metric_id(), valueChange.id());
1495 EXPECT_TRUE(valueChangeAfter.has_value_metrics());
1496 valueMetrics.Clear();
1497 sortMetricDataByDimensionsValue(valueChangeAfter.value_metrics(), &valueMetrics);
1498 int64_t conditionTrueNs = bucketSizeNs - 60 * NS_PER_SEC + 10 * NS_PER_SEC;
1499 ASSERT_EQ(valueMetrics.data_size(), 2);
1500 data = valueMetrics.data(0);
1501 ValidateSubsystemSleepDimension(data.dimensions_in_what(), "subsystem_name_1");
1502 ASSERT_EQ(data.bucket_info_size(), 1);
1503 ValidateValueBucket(data.bucket_info(0), roundedUpdateTimeNs, roundedBucketEndNs, {3500},
1504 conditionTrueNs);
1505 ASSERT_EQ(valueMetrics.data_size(), 2);
1506 data = valueMetrics.data(1);
1507 ValidateSubsystemSleepDimension(data.dimensions_in_what(), "subsystem_name_2");
1508 ASSERT_EQ(data.bucket_info_size(), 1);
1509 ValidateValueBucket(data.bucket_info(0), roundedUpdateTimeNs, roundedBucketEndNs, {3500},
1510 conditionTrueNs);
1511
1512 ASSERT_EQ(valueChangeAfter.value_metrics().skipped_size(), 1);
1513 skipBucket = valueChangeAfter.value_metrics().skipped(0);
1514 EXPECT_EQ(skipBucket.start_bucket_elapsed_nanos(), roundedBucketEndNs);
1515 EXPECT_EQ(skipBucket.end_bucket_elapsed_nanos(), roundedDumpTimeNs);
1516 ASSERT_EQ(skipBucket.drop_event_size(), 1);
1517 EXPECT_EQ(skipBucket.drop_event(0).drop_reason(), BucketDropReason::DUMP_REPORT_REQUESTED);
1518
1519 // Max screen brightness, no condition. Val is 40 in first bucket, 50 in second.
1520 StatsLogReport valueNewAfter = report.metrics(1);
1521 EXPECT_EQ(valueNewAfter.metric_id(), valueNew.id());
1522 EXPECT_TRUE(valueNewAfter.has_value_metrics());
1523 valueMetrics.Clear();
1524 sortMetricDataByDimensionsValue(valueNewAfter.value_metrics(), &valueMetrics);
1525 ASSERT_EQ(valueMetrics.data_size(), 1);
1526 data = valueMetrics.data(0);
1527 ASSERT_EQ(data.bucket_info_size(), 2);
1528 ValidateValueBucket(data.bucket_info(0), roundedUpdateTimeNs, roundedBucketEndNs, {40}, 0);
1529 ValidateValueBucket(data.bucket_info(1), roundedBucketEndNs, roundedDumpTimeNs, {50}, 0);
1530
1531 // Min screen brightness when screen on. Val is 30 in first bucket, 50 in second.
1532 StatsLogReport valuePushPersistAfter = report.metrics(2);
1533 EXPECT_EQ(valuePushPersistAfter.metric_id(), valuePushPersist.id());
1534 EXPECT_TRUE(valuePushPersistAfter.has_value_metrics());
1535 valueMetrics.Clear();
1536 sortMetricDataByDimensionsValue(valuePushPersistAfter.value_metrics(), &valueMetrics);
1537 ASSERT_EQ(valueMetrics.data_size(), 1);
1538 data = valueMetrics.data(0);
1539 ASSERT_EQ(data.bucket_info_size(), 2);
1540 conditionTrueNs = bucketSizeNs - 60 * NS_PER_SEC + 10 * NS_PER_SEC;
1541 ValidateValueBucket(data.bucket_info(0), roundedUpdateTimeNs, roundedBucketEndNs, {30},
1542 conditionTrueNs);
1543 ValidateValueBucket(data.bucket_info(1), roundedBucketEndNs, roundedDumpTimeNs, {50},
1544 10 * NS_PER_SEC);
1545
1546 // TODO(b/179725160): fix assertions.
1547 // Subsystem sleep state while unplugged slice screen.
1548 StatsLogReport valuePullPersistAfter = report.metrics(3);
1549 EXPECT_EQ(valuePullPersistAfter.metric_id(), valuePullPersist.id());
1550 EXPECT_TRUE(valuePullPersistAfter.has_value_metrics());
1551 valueMetrics.Clear();
1552 sortMetricDataByDimensionsValue(valuePullPersistAfter.value_metrics(), &valueMetrics);
1553 ASSERT_EQ(valueMetrics.data_size(), 4);
1554 // Name 1, screen OFF. Pull#5 (2500) - pull#4 (1600).
1555 data = valueMetrics.data(0);
1556 conditionTrueNs = 10 * NS_PER_SEC;
1557 ValidateSubsystemSleepDimension(data.dimensions_in_what(), "subsystem_name_1");
1558 ValidateStateValue(data.slice_by_state(), util::SCREEN_STATE_CHANGED,
1559 android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
1560 ASSERT_EQ(data.bucket_info_size(), 1);
1561 ValidateValueBucket(data.bucket_info(0), roundedUpdateTimeNs, roundedBucketEndNs, {900}, -1);
1562 // Name 1, screen ON. Pull#4 (1600) - pull#3 (900) + pull#8 (6400) - pull#7 (4900).
1563 data = valueMetrics.data(1);
1564 conditionTrueNs = 10 * NS_PER_SEC + bucketSizeNs - 65 * NS_PER_SEC;
1565 ValidateSubsystemSleepDimension(data.dimensions_in_what(), "subsystem_name_1");
1566 ValidateStateValue(data.slice_by_state(), util::SCREEN_STATE_CHANGED,
1567 android::view::DisplayStateEnum::DISPLAY_STATE_ON);
1568 ASSERT_EQ(data.bucket_info_size(), 1);
1569 ValidateValueBucket(data.bucket_info(0), roundedUpdateTimeNs, roundedBucketEndNs, {2200}, -1);
1570 // Name 2, screen OFF. Pull#5 (2500) - pull#4 (1600).
1571 data = valueMetrics.data(2);
1572 conditionTrueNs = 10 * NS_PER_SEC;
1573 ValidateSubsystemSleepDimension(data.dimensions_in_what(), "subsystem_name_2");
1574 ValidateStateValue(data.slice_by_state(), util::SCREEN_STATE_CHANGED,
1575 android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
1576 ASSERT_EQ(data.bucket_info_size(), 1);
1577 ValidateValueBucket(data.bucket_info(0), roundedUpdateTimeNs, roundedBucketEndNs, {900}, -1);
1578 // Name 2, screen ON. Pull#4 (1600) - pull#3 (900) + pull#8 (6400) - pull#7 (4900).
1579 data = valueMetrics.data(3);
1580 conditionTrueNs = 10 * NS_PER_SEC + bucketSizeNs - 65 * NS_PER_SEC;
1581 ValidateSubsystemSleepDimension(data.dimensions_in_what(), "subsystem_name_2");
1582 ValidateStateValue(data.slice_by_state(), util::SCREEN_STATE_CHANGED,
1583 android::view::DisplayStateEnum::DISPLAY_STATE_ON);
1584 ASSERT_EQ(data.bucket_info_size(), 1);
1585 ValidateValueBucket(data.bucket_info(0), roundedUpdateTimeNs, roundedBucketEndNs, {2200}, -1);
1586
1587 ASSERT_EQ(valuePullPersistAfter.value_metrics().skipped_size(), 1);
1588 skipBucket = valuePullPersistAfter.value_metrics().skipped(0);
1589 EXPECT_EQ(skipBucket.start_bucket_elapsed_nanos(), roundedBucketEndNs);
1590 EXPECT_EQ(skipBucket.end_bucket_elapsed_nanos(), roundedDumpTimeNs);
1591 ASSERT_EQ(skipBucket.drop_event_size(), 1);
1592 EXPECT_EQ(skipBucket.drop_event(0).drop_reason(), BucketDropReason::DUMP_REPORT_REQUESTED);
1593 }
1594
TEST_F(ConfigUpdateE2eTest,TestMetricActivation)1595 TEST_F(ConfigUpdateE2eTest, TestMetricActivation) {
1596 StatsdConfig config;
1597 config.add_allowed_log_source("AID_ROOT");
1598
1599 string immediateTag = "immediate", bootTag = "boot", childTag = "child";
1600
1601 AtomMatcher syncStartMatcher = CreateSyncStartAtomMatcher();
1602 *config.add_atom_matcher() = syncStartMatcher;
1603
1604 AtomMatcher immediateMatcher =
1605 CreateSimpleAtomMatcher("immediateMatcher", util::WAKELOCK_STATE_CHANGED);
1606 FieldValueMatcher* fvm =
1607 immediateMatcher.mutable_simple_atom_matcher()->add_field_value_matcher();
1608 fvm->set_field(3); // Tag.
1609 fvm->set_eq_string(immediateTag);
1610 *config.add_atom_matcher() = immediateMatcher;
1611
1612 AtomMatcher bootMatcher = CreateSimpleAtomMatcher("bootMatcher", util::WAKELOCK_STATE_CHANGED);
1613 fvm = bootMatcher.mutable_simple_atom_matcher()->add_field_value_matcher();
1614 fvm->set_field(3); // Tag.
1615 fvm->set_eq_string(bootTag);
1616 *config.add_atom_matcher() = bootMatcher;
1617
1618 AtomMatcher childMatcher =
1619 CreateSimpleAtomMatcher("childMatcher", util::WAKELOCK_STATE_CHANGED);
1620 fvm = childMatcher.mutable_simple_atom_matcher()->add_field_value_matcher();
1621 fvm->set_field(3); // Tag.
1622 fvm->set_eq_string(childTag);
1623 *config.add_atom_matcher() = childMatcher;
1624
1625 AtomMatcher acquireMatcher = CreateAcquireWakelockAtomMatcher();
1626 *config.add_atom_matcher() = acquireMatcher;
1627
1628 AtomMatcher combinationMatcher;
1629 combinationMatcher.set_id(StringToId("combination"));
1630 AtomMatcher_Combination* combination = combinationMatcher.mutable_combination();
1631 combination->set_operation(LogicalOperation::OR);
1632 combination->add_matcher(acquireMatcher.id());
1633 combination->add_matcher(childMatcher.id());
1634 *config.add_atom_matcher() = combinationMatcher;
1635
1636 CountMetric immediateMetric =
1637 createCountMetric("ImmediateMetric", syncStartMatcher.id(), nullopt, {});
1638 CountMetric bootMetric = createCountMetric("BootMetric", syncStartMatcher.id(), nullopt, {});
1639 CountMetric combinationMetric =
1640 createCountMetric("CombinationMetric", syncStartMatcher.id(), nullopt, {});
1641 *config.add_count_metric() = immediateMetric;
1642 *config.add_count_metric() = bootMetric;
1643 *config.add_count_metric() = combinationMetric;
1644
1645 MetricActivation immediateMetricActivation;
1646 immediateMetricActivation.set_metric_id(immediateMetric.id());
1647 auto eventActivation = immediateMetricActivation.add_event_activation();
1648 eventActivation->set_activation_type(ActivationType::ACTIVATE_IMMEDIATELY);
1649 eventActivation->set_atom_matcher_id(immediateMatcher.id());
1650 eventActivation->set_ttl_seconds(60); // One minute.
1651 *config.add_metric_activation() = immediateMetricActivation;
1652
1653 MetricActivation bootMetricActivation;
1654 bootMetricActivation.set_metric_id(bootMetric.id());
1655 eventActivation = bootMetricActivation.add_event_activation();
1656 eventActivation->set_activation_type(ActivationType::ACTIVATE_ON_BOOT);
1657 eventActivation->set_atom_matcher_id(bootMatcher.id());
1658 eventActivation->set_ttl_seconds(60); // One minute.
1659 *config.add_metric_activation() = bootMetricActivation;
1660
1661 MetricActivation combinationMetricActivation;
1662 combinationMetricActivation.set_metric_id(combinationMetric.id());
1663 eventActivation = combinationMetricActivation.add_event_activation();
1664 eventActivation->set_activation_type(ActivationType::ACTIVATE_IMMEDIATELY);
1665 eventActivation->set_atom_matcher_id(combinationMatcher.id());
1666 eventActivation->set_ttl_seconds(60); // One minute.
1667 *config.add_metric_activation() = combinationMetricActivation;
1668
1669 ConfigKey key(123, 987);
1670 uint64_t bucketStartTimeNs = 10000000000; // 0:10
1671 uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(TEN_MINUTES) * 1000000LL;
1672 sp<StatsLogProcessor> processor =
1673 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, key);
1674 int uid1 = 55555;
1675
1676 // Initialize log events before update.
1677 // Counts provided in order of immediate, boot, and combination metric.
1678 std::vector<std::unique_ptr<LogEvent>> events;
1679
1680 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 5 * NS_PER_SEC, {uid1}, {""},
1681 "")); // Count: 0, 0, 0.
1682 events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 10 * NS_PER_SEC, {uid1}, {""},
1683 immediateTag)); // Activate immediate metric.
1684 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 15 * NS_PER_SEC, {uid1}, {""},
1685 "")); // Count: 1, 0, 0.
1686 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 20 * NS_PER_SEC, {uid1}, {""},
1687 "foo")); // Activate combination metric.
1688 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 25 * NS_PER_SEC, {uid1}, {""},
1689 "")); // Count: 2, 0, 1.
1690 events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 30 * NS_PER_SEC, {uid1}, {""},
1691 bootTag)); // Boot metric pending activation.
1692 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 35 * NS_PER_SEC, {uid1}, {""},
1693 "")); // Count: 3, 0, 2.
1694 // Send log events to StatsLogProcessor.
1695 for (auto& event : events) {
1696 processor->OnLogEvent(event.get());
1697 }
1698
1699 // Do update. Add matchers/conditions in different order to force indices to change.
1700 StatsdConfig newConfig;
1701 newConfig.add_allowed_log_source("AID_ROOT");
1702 newConfig.set_hash_strings_in_metric_report(false); // Modify metadata for fun.
1703
1704 // Change combination matcher, will mean combination metric isn't active after update.
1705 combinationMatcher.mutable_combination()->set_operation(LogicalOperation::AND);
1706 *newConfig.add_atom_matcher() = acquireMatcher;
1707 *newConfig.add_atom_matcher() = bootMatcher;
1708 *newConfig.add_atom_matcher() = combinationMatcher;
1709 *newConfig.add_atom_matcher() = childMatcher;
1710 *newConfig.add_atom_matcher() = syncStartMatcher;
1711 *newConfig.add_atom_matcher() = immediateMatcher;
1712
1713 *newConfig.add_count_metric() = bootMetric;
1714 *newConfig.add_count_metric() = combinationMetric;
1715 *newConfig.add_count_metric() = immediateMetric;
1716
1717 *newConfig.add_metric_activation() = bootMetricActivation;
1718 *newConfig.add_metric_activation() = combinationMetricActivation;
1719 *newConfig.add_metric_activation() = immediateMetricActivation;
1720
1721 int64_t updateTimeNs = bucketStartTimeNs + 40 * NS_PER_SEC;
1722 processor->OnConfigUpdated(updateTimeNs, key, newConfig);
1723
1724 // The reboot will write to disk again, so sleep for 1 second to avoid this.
1725 // TODO(b/178887128): clean this up.
1726 std::this_thread::sleep_for(1000ms);
1727 // Send event after the update. Counts reset to 0 since this is a new bucket.
1728 processor->OnLogEvent(
1729 CreateSyncStartEvent(bucketStartTimeNs + 45 * NS_PER_SEC, {uid1}, {""}, "")
1730 .get()); // Count: 1, 0, 0.
1731
1732 // Fake a reboot. Code is from StatsService::informDeviceShutdown.
1733 int64_t shutDownTimeNs = bucketStartTimeNs + 50 * NS_PER_SEC;
1734 processor->WriteDataToDisk(DEVICE_SHUTDOWN, FAST, shutDownTimeNs);
1735 processor->SaveActiveConfigsToDisk(shutDownTimeNs);
1736 processor->SaveMetadataToDisk(getWallClockNs(), shutDownTimeNs);
1737
1738 // On boot, use StartUp. However, skip config manager for simplicity.
1739 int64_t bootTimeNs = bucketStartTimeNs + 55 * NS_PER_SEC;
1740 processor = CreateStatsLogProcessor(bootTimeNs, bootTimeNs, newConfig, key);
1741 processor->LoadActiveConfigsFromDisk();
1742 processor->LoadMetadataFromDisk(getWallClockNs(), bootTimeNs);
1743
1744 // Send events after boot. Counts reset to 0 since this is a new bucket. Boot metric now active.
1745 events.clear();
1746 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 60 * NS_PER_SEC, {uid1}, {""},
1747 "")); // Count: 1, 1, 0.
1748 int64_t deactivationTimeNs = bucketStartTimeNs + 76 * NS_PER_SEC;
1749 events.push_back(CreateScreenStateChangedEvent(
1750 deactivationTimeNs,
1751 android::view::DisplayStateEnum::DISPLAY_STATE_OFF)); // TTLs immediate metric.
1752 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 80 * NS_PER_SEC, {uid1}, {""},
1753 "")); // Count: 1, 2, 0.
1754 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 85 * NS_PER_SEC, {uid1}, {""},
1755 childTag)); // Activate combination metric.
1756 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 90 * NS_PER_SEC, {uid1}, {""},
1757 "")); // Count: 1, 3, 1.
1758
1759 // Send log events to StatsLogProcessor.
1760 for (auto& event : events) {
1761 processor->OnLogEvent(event.get());
1762 }
1763 uint64_t dumpTimeNs = bucketStartTimeNs + 90 * NS_PER_SEC;
1764 ConfigMetricsReportList reports;
1765 vector<uint8_t> buffer;
1766 processor->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, FAST, &buffer);
1767 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1768 backfillDimensionPath(&reports);
1769 backfillStringInReport(&reports);
1770 backfillStartEndTimestamp(&reports);
1771 ASSERT_EQ(reports.reports_size(), 3);
1772
1773 // Report from before update.
1774 ConfigMetricsReport report = reports.reports(0);
1775 EXPECT_EQ(report.last_report_elapsed_nanos(), bucketStartTimeNs);
1776 EXPECT_EQ(report.current_report_elapsed_nanos(), updateTimeNs);
1777 ASSERT_EQ(report.metrics_size(), 3);
1778 // Immediate metric. Count = 3.
1779 StatsLogReport metricReport = report.metrics(0);
1780 EXPECT_EQ(metricReport.metric_id(), immediateMetric.id());
1781 EXPECT_TRUE(metricReport.is_active());
1782 EXPECT_TRUE(metricReport.has_count_metrics());
1783 ASSERT_EQ(metricReport.count_metrics().data_size(), 1);
1784 auto data = metricReport.count_metrics().data(0);
1785 ASSERT_EQ(data.bucket_info_size(), 1);
1786 ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, updateTimeNs, 3);
1787
1788 // Boot metric. Count = 0.
1789 metricReport = report.metrics(1);
1790 EXPECT_EQ(metricReport.metric_id(), bootMetric.id());
1791 EXPECT_FALSE(metricReport.is_active());
1792 EXPECT_FALSE(metricReport.has_count_metrics());
1793
1794 // Combination metric. Count = 2.
1795 metricReport = report.metrics(2);
1796 EXPECT_EQ(metricReport.metric_id(), combinationMetric.id());
1797 EXPECT_TRUE(metricReport.is_active());
1798 EXPECT_TRUE(metricReport.has_count_metrics());
1799 ASSERT_EQ(metricReport.count_metrics().data_size(), 1);
1800 data = metricReport.count_metrics().data(0);
1801 ASSERT_EQ(data.bucket_info_size(), 1);
1802 ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, updateTimeNs, 2);
1803
1804 // Report from after update, before boot.
1805 report = reports.reports(1);
1806 EXPECT_EQ(report.last_report_elapsed_nanos(), updateTimeNs);
1807 EXPECT_EQ(report.current_report_elapsed_nanos(), shutDownTimeNs);
1808 ASSERT_EQ(report.metrics_size(), 3);
1809 // Boot metric. Count = 0.
1810 metricReport = report.metrics(0);
1811 EXPECT_EQ(metricReport.metric_id(), bootMetric.id());
1812 EXPECT_FALSE(metricReport.is_active());
1813 EXPECT_FALSE(metricReport.has_count_metrics());
1814
1815 // Combination metric. Count = 0.
1816 metricReport = report.metrics(1);
1817 EXPECT_EQ(metricReport.metric_id(), combinationMetric.id());
1818 EXPECT_FALSE(metricReport.is_active());
1819 EXPECT_FALSE(metricReport.has_count_metrics());
1820
1821 // Immediate metric. Count = 1.
1822 metricReport = report.metrics(2);
1823 EXPECT_EQ(metricReport.metric_id(), immediateMetric.id());
1824 EXPECT_TRUE(metricReport.is_active());
1825 EXPECT_TRUE(metricReport.has_count_metrics());
1826 ASSERT_EQ(metricReport.count_metrics().data_size(), 1);
1827 data = metricReport.count_metrics().data(0);
1828 ASSERT_EQ(data.bucket_info_size(), 1);
1829 ValidateCountBucket(data.bucket_info(0), updateTimeNs, shutDownTimeNs, 1);
1830
1831 // Report from after reboot.
1832 report = reports.reports(2);
1833 EXPECT_EQ(report.last_report_elapsed_nanos(), bootTimeNs);
1834 EXPECT_EQ(report.current_report_elapsed_nanos(), dumpTimeNs);
1835 ASSERT_EQ(report.metrics_size(), 3);
1836 // Boot metric. Count = 3.
1837 metricReport = report.metrics(0);
1838 EXPECT_EQ(metricReport.metric_id(), bootMetric.id());
1839 EXPECT_TRUE(metricReport.is_active());
1840 EXPECT_TRUE(metricReport.has_count_metrics());
1841 ASSERT_EQ(metricReport.count_metrics().data_size(), 1);
1842 data = metricReport.count_metrics().data(0);
1843 ASSERT_EQ(data.bucket_info_size(), 1);
1844 ValidateCountBucket(data.bucket_info(0), bootTimeNs, dumpTimeNs, 3);
1845
1846 // Combination metric. Count = 1.
1847 metricReport = report.metrics(1);
1848 EXPECT_EQ(metricReport.metric_id(), combinationMetric.id());
1849 EXPECT_TRUE(metricReport.is_active());
1850 EXPECT_TRUE(metricReport.has_count_metrics());
1851 ASSERT_EQ(metricReport.count_metrics().data_size(), 1);
1852 data = metricReport.count_metrics().data(0);
1853 ASSERT_EQ(data.bucket_info_size(), 1);
1854 ValidateCountBucket(data.bucket_info(0), bootTimeNs, dumpTimeNs, 1);
1855
1856 // Immediate metric. Count = 1.
1857 metricReport = report.metrics(2);
1858 EXPECT_EQ(metricReport.metric_id(), immediateMetric.id());
1859 EXPECT_FALSE(metricReport.is_active());
1860 EXPECT_TRUE(metricReport.has_count_metrics());
1861 ASSERT_EQ(metricReport.count_metrics().data_size(), 1);
1862 data = metricReport.count_metrics().data(0);
1863 ASSERT_EQ(data.bucket_info_size(), 1);
1864 ValidateCountBucket(data.bucket_info(0), bootTimeNs, deactivationTimeNs, 1);
1865 }
1866
TEST_F(ConfigUpdateE2eTest,TestAnomalyCountMetric)1867 TEST_F(ConfigUpdateE2eTest, TestAnomalyCountMetric) {
1868 StatsdConfig config;
1869 config.add_allowed_log_source("AID_ROOT");
1870
1871 AtomMatcher syncStartMatcher = CreateSyncStartAtomMatcher();
1872 *config.add_atom_matcher() = syncStartMatcher;
1873 AtomMatcher wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
1874 *config.add_atom_matcher() = wakelockAcquireMatcher;
1875
1876 CountMetric countWakelock =
1877 createCountMetric("CountWakelock", wakelockAcquireMatcher.id(), nullopt, {});
1878 *countWakelock.mutable_dimensions_in_what() =
1879 CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
1880
1881 CountMetric countSync = createCountMetric("CountSync", syncStartMatcher.id(), nullopt, {});
1882 *countSync.mutable_dimensions_in_what() =
1883 CreateAttributionUidDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST});
1884
1885 *config.add_count_metric() = countWakelock;
1886 *config.add_count_metric() = countSync;
1887
1888 Alert alertPreserve =
1889 createAlert("AlertPreserve", countWakelock.id(), /*buckets=*/2, /*triggerSumGt=*/1);
1890 alertPreserve.set_refractory_period_secs(20);
1891 Alert alertReplace = createAlert("AlertReplace", countSync.id(), 1, 1);
1892 alertReplace.set_refractory_period_secs(1);
1893 Alert alertRemove = createAlert("AlertRemove", countWakelock.id(), 1, 0);
1894 alertRemove.set_refractory_period_secs(1);
1895 *config.add_alert() = alertReplace;
1896 *config.add_alert() = alertPreserve;
1897 *config.add_alert() = alertRemove;
1898
1899 int preserveSubId = 1, replaceSubId = 2, removeSubId = 3;
1900 Subscription preserveSub = createSubscription("S1", Subscription::ALERT, alertPreserve.id());
1901 preserveSub.mutable_broadcast_subscriber_details()->set_subscriber_id(preserveSubId);
1902 Subscription replaceSub = createSubscription("S2", Subscription::ALERT, alertReplace.id());
1903 replaceSub.mutable_broadcast_subscriber_details()->set_subscriber_id(replaceSubId);
1904 Subscription removeSub = createSubscription("S3", Subscription::ALERT, alertRemove.id());
1905 removeSub.mutable_broadcast_subscriber_details()->set_subscriber_id(removeSubId);
1906 *config.add_subscription() = preserveSub;
1907 *config.add_subscription() = removeSub;
1908 *config.add_subscription() = replaceSub;
1909
1910 int app1Uid = 123, app2Uid = 456;
1911 vector<int> attributionUids1 = {app1Uid};
1912 vector<string> attributionTags1 = {"App1"};
1913 vector<int> attributionUids2 = {app2Uid};
1914 vector<string> attributionTags2 = {"App2"};
1915 int64_t configUid = 123, configId = 987;
1916 ConfigKey key(configUid, configId);
1917
1918 int alertPreserveCount = 0, alertRemoveCount = 0;
1919 StatsDimensionsValueParcel alertPreserveDims;
1920 StatsDimensionsValueParcel alertRemoveDims;
1921
1922 // The binder calls here will happen synchronously because they are in-process.
1923 shared_ptr<MockPendingIntentRef> preserveBroadcast =
1924 SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
1925 EXPECT_CALL(*preserveBroadcast, sendSubscriberBroadcast(configUid, configId, preserveSub.id(),
1926 alertPreserve.id(), _, _))
1927 .Times(2)
1928 .WillRepeatedly(
1929 Invoke([&alertPreserveCount, &alertPreserveDims](
1930 int64_t, int64_t, int64_t, int64_t, const vector<string>&,
1931 const StatsDimensionsValueParcel& dimensionsValueParcel) {
1932 alertPreserveCount++;
1933 alertPreserveDims = dimensionsValueParcel;
1934 return Status::ok();
1935 }));
1936
1937 shared_ptr<MockPendingIntentRef> replaceBroadcast =
1938 SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
1939 EXPECT_CALL(*replaceBroadcast, sendSubscriberBroadcast(configUid, configId, replaceSub.id(),
1940 alertReplace.id(), _, _))
1941 .Times(0);
1942
1943 shared_ptr<MockPendingIntentRef> removeBroadcast =
1944 SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
1945 EXPECT_CALL(*removeBroadcast, sendSubscriberBroadcast(configUid, configId, removeSub.id(),
1946 alertRemove.id(), _, _))
1947 .Times(3)
1948 .WillRepeatedly(
1949 Invoke([&alertRemoveCount, &alertRemoveDims](
1950 int64_t, int64_t, int64_t, int64_t, const vector<string>&,
1951 const StatsDimensionsValueParcel& dimensionsValueParcel) {
1952 alertRemoveCount++;
1953 alertRemoveDims = dimensionsValueParcel;
1954 return Status::ok();
1955 }));
1956
1957 SubscriberReporter::getInstance().setBroadcastSubscriber(key, preserveSubId, preserveBroadcast);
1958 SubscriberReporter::getInstance().setBroadcastSubscriber(key, replaceSubId, replaceBroadcast);
1959 SubscriberReporter::getInstance().setBroadcastSubscriber(key, removeSubId, removeBroadcast);
1960
1961 uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(TEN_MINUTES) * 1000000LL;
1962 uint64_t bucketStartTimeNs = 10000000000; // 0:10
1963 uint64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
1964 sp<StatsLogProcessor> processor =
1965 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, key);
1966
1967 StatsDimensionsValueParcel wlUid1 =
1968 CreateAttributionUidDimensionsValueParcel(util::WAKELOCK_STATE_CHANGED, app1Uid);
1969 StatsDimensionsValueParcel wlUid2 =
1970 CreateAttributionUidDimensionsValueParcel(util::WAKELOCK_STATE_CHANGED, app2Uid);
1971
1972 processor->OnLogEvent(CreateAcquireWakelockEvent(bucketStartTimeNs + 15 * NS_PER_SEC,
1973 attributionUids1, attributionTags1, "wl1")
1974 .get());
1975 EXPECT_EQ(alertPreserveCount, 0);
1976 EXPECT_EQ(alertRemoveCount, 1);
1977 EXPECT_EQ(alertRemoveDims, wlUid1);
1978
1979 processor->OnLogEvent(CreateAcquireWakelockEvent(bucketStartTimeNs + 20 * NS_PER_SEC,
1980 attributionUids2, attributionTags2, "wl2")
1981 .get());
1982 EXPECT_EQ(alertPreserveCount, 0);
1983 EXPECT_EQ(alertRemoveCount, 2);
1984 EXPECT_EQ(alertRemoveDims, wlUid2);
1985
1986 processor->OnLogEvent(CreateSyncStartEvent(bucket2StartTimeNs + 5 * NS_PER_SEC,
1987 attributionUids1, attributionTags1, "sync1")
1988 .get());
1989 EXPECT_EQ(alertPreserveCount, 0);
1990 EXPECT_EQ(alertRemoveCount, 2);
1991
1992 // AlertPreserve enters 30 sec refractory period for uid2.
1993 processor->OnLogEvent(CreateAcquireWakelockEvent(bucket2StartTimeNs + 10 * NS_PER_SEC,
1994 attributionUids2, attributionTags2, "wl2")
1995 .get());
1996 EXPECT_EQ(alertPreserveCount, 1);
1997 EXPECT_EQ(alertPreserveDims, wlUid2);
1998 EXPECT_EQ(alertRemoveCount, 3);
1999 EXPECT_EQ(alertRemoveDims, wlUid2);
2000
2001 // Do config update.
2002 StatsdConfig newConfig;
2003 newConfig.add_allowed_log_source("AID_ROOT");
2004 *newConfig.add_atom_matcher() = wakelockAcquireMatcher;
2005 *newConfig.add_atom_matcher() = syncStartMatcher;
2006
2007 // Clear dims of sync metric, will result in alertReplace getting replaced.
2008 countSync.clear_dimensions_in_what();
2009 *newConfig.add_count_metric() = countSync;
2010 *newConfig.add_count_metric() = countWakelock;
2011
2012 // New alert on existing metric. Should get current full bucket, but not history of 1st bucket.
2013 Alert alertNew = createAlert("AlertNew", countWakelock.id(), /*buckets=*/1, /*triggerSumGt=*/1);
2014 *newConfig.add_alert() = alertPreserve;
2015 *newConfig.add_alert() = alertNew;
2016 *newConfig.add_alert() = alertReplace;
2017
2018 int newSubId = 4;
2019 Subscription newSub = createSubscription("S4", Subscription::ALERT, alertNew.id());
2020 newSub.mutable_broadcast_subscriber_details()->set_subscriber_id(newSubId);
2021 *newConfig.add_subscription() = newSub;
2022 *newConfig.add_subscription() = replaceSub;
2023 *newConfig.add_subscription() = preserveSub;
2024
2025 int alertNewCount = 0;
2026 StatsDimensionsValueParcel alertNewDims;
2027 shared_ptr<MockPendingIntentRef> newBroadcast =
2028 SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
2029 EXPECT_CALL(*newBroadcast,
2030 sendSubscriberBroadcast(configUid, configId, newSub.id(), alertNew.id(), _, _))
2031 .Times(1)
2032 .WillRepeatedly(
2033 Invoke([&alertNewCount, &alertNewDims](
2034 int64_t, int64_t, int64_t, int64_t, const vector<string>&,
2035 const StatsDimensionsValueParcel& dimensionsValueParcel) {
2036 alertNewCount++;
2037 alertNewDims = dimensionsValueParcel;
2038 return Status::ok();
2039 }));
2040 SubscriberReporter::getInstance().setBroadcastSubscriber(key, newSubId, newBroadcast);
2041
2042 int64_t updateTimeNs = bucket2StartTimeNs + 15 * NS_PER_SEC;
2043 processor->OnConfigUpdated(updateTimeNs, key, newConfig);
2044
2045 // Within refractory of AlertPreserve, but AlertNew should fire since the full bucket has 2.
2046 processor->OnLogEvent(CreateAcquireWakelockEvent(bucket2StartTimeNs + 20 * NS_PER_SEC,
2047 attributionUids2, attributionTags2, "wl2")
2048 .get());
2049 EXPECT_EQ(alertPreserveCount, 1);
2050 EXPECT_EQ(alertNewCount, 1);
2051 EXPECT_EQ(alertNewDims, wlUid2);
2052
2053 // Wakelock for uid1 fired in first bucket, alert preserve should keep the history and fire.
2054 processor->OnLogEvent(CreateAcquireWakelockEvent(bucket2StartTimeNs + 25 * NS_PER_SEC,
2055 attributionUids1, attributionTags1, "wl1")
2056 .get());
2057 EXPECT_EQ(alertPreserveCount, 2);
2058 EXPECT_EQ(alertPreserveDims, wlUid1);
2059 EXPECT_EQ(alertNewCount, 1);
2060
2061 processor->OnLogEvent(CreateSyncStartEvent(bucket2StartTimeNs + 30 * NS_PER_SEC,
2062 attributionUids1, attributionTags1, "sync1")
2063 .get());
2064 EXPECT_EQ(alertPreserveCount, 2);
2065 EXPECT_EQ(alertNewCount, 1);
2066 EXPECT_EQ(alertRemoveCount, 3);
2067
2068 // Clear data so it doesn't stay on disk.
2069 vector<uint8_t> buffer;
2070 processor->onDumpReport(key, bucket2StartTimeNs + 100 * NS_PER_SEC, true, true, ADB_DUMP, FAST,
2071 &buffer);
2072 SubscriberReporter::getInstance().unsetBroadcastSubscriber(key, preserveSubId);
2073 SubscriberReporter::getInstance().unsetBroadcastSubscriber(key, replaceSubId);
2074 SubscriberReporter::getInstance().unsetBroadcastSubscriber(key, removeSubId);
2075 SubscriberReporter::getInstance().unsetBroadcastSubscriber(key, newSubId);
2076 }
2077
TEST_F(ConfigUpdateE2eTest,TestAnomalyDurationMetric)2078 TEST_F(ConfigUpdateE2eTest, TestAnomalyDurationMetric) {
2079 StatsdConfig config;
2080 config.add_allowed_log_source("AID_ROOT");
2081
2082 AtomMatcher wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
2083 *config.add_atom_matcher() = wakelockAcquireMatcher;
2084 AtomMatcher wakelockReleaseMatcher = CreateReleaseWakelockAtomMatcher();
2085 *config.add_atom_matcher() = wakelockReleaseMatcher;
2086 AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
2087 *config.add_atom_matcher() = screenOnMatcher;
2088 AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
2089 *config.add_atom_matcher() = screenOffMatcher;
2090
2091 Predicate holdingWakelockPredicate = CreateHoldingWakelockPredicate();
2092 *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() =
2093 CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
2094 *config.add_predicate() = holdingWakelockPredicate;
2095 Predicate screenOnPredicate = CreateScreenIsOnPredicate();
2096 *config.add_predicate() = screenOnPredicate;
2097
2098 DurationMetric durationWakelock =
2099 createDurationMetric("DurWakelock", holdingWakelockPredicate.id(), nullopt, {});
2100 *durationWakelock.mutable_dimensions_in_what() =
2101 CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
2102 DurationMetric durationScreen =
2103 createDurationMetric("DurScreen", screenOnPredicate.id(), nullopt, {});
2104 *config.add_duration_metric() = durationScreen;
2105 *config.add_duration_metric() = durationWakelock;
2106
2107 Alert alertPreserve = createAlert("AlertPreserve", durationWakelock.id(), /*buckets=*/2,
2108 /*triggerSumGt=*/30 * NS_PER_SEC);
2109 alertPreserve.set_refractory_period_secs(300);
2110 Alert alertReplace = createAlert("AlertReplace", durationScreen.id(), 2, 30 * NS_PER_SEC);
2111 alertReplace.set_refractory_period_secs(1);
2112 Alert alertRemove = createAlert("AlertRemove", durationWakelock.id(), 5, 10 * NS_PER_SEC);
2113 alertRemove.set_refractory_period_secs(1);
2114 *config.add_alert() = alertReplace;
2115 *config.add_alert() = alertPreserve;
2116 *config.add_alert() = alertRemove;
2117
2118 int preserveSubId = 1, replaceSubId = 2, removeSubId = 3;
2119 Subscription preserveSub = createSubscription("S1", Subscription::ALERT, alertPreserve.id());
2120 preserveSub.mutable_broadcast_subscriber_details()->set_subscriber_id(preserveSubId);
2121 Subscription replaceSub = createSubscription("S2", Subscription::ALERT, alertReplace.id());
2122 replaceSub.mutable_broadcast_subscriber_details()->set_subscriber_id(replaceSubId);
2123 Subscription removeSub = createSubscription("S3", Subscription::ALERT, alertRemove.id());
2124 removeSub.mutable_broadcast_subscriber_details()->set_subscriber_id(removeSubId);
2125 *config.add_subscription() = preserveSub;
2126 *config.add_subscription() = removeSub;
2127 *config.add_subscription() = replaceSub;
2128
2129 int app1Uid = 123, app2Uid = 456, app3Uid = 789, app4Uid = 111;
2130 vector<int> attributionUids1 = {app1Uid}, attributionUids2 = {app2Uid},
2131 attributionUids3 = {app3Uid}, attributionUids4 = {app4Uid};
2132 vector<string> attributionTags1 = {"App1"}, attributionTags2 = {"App2"},
2133 attributionTags3 = {"App3"}, attributionTags4 = {"App4"};
2134
2135 int64_t configUid = 123, configId = 987;
2136 ConfigKey key(configUid, configId);
2137
2138 int alertPreserveCount = 0, alertRemoveCount = 0;
2139 StatsDimensionsValueParcel alertPreserveDims;
2140 StatsDimensionsValueParcel alertRemoveDims;
2141
2142 // The binder calls here will happen synchronously because they are in-process.
2143 shared_ptr<MockPendingIntentRef> preserveBroadcast =
2144 SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
2145 EXPECT_CALL(*preserveBroadcast, sendSubscriberBroadcast(configUid, configId, preserveSub.id(),
2146 alertPreserve.id(), _, _))
2147 .Times(4)
2148 .WillRepeatedly(
2149 Invoke([&alertPreserveCount, &alertPreserveDims](
2150 int64_t, int64_t, int64_t, int64_t, const vector<string>&,
2151 const StatsDimensionsValueParcel& dimensionsValueParcel) {
2152 alertPreserveCount++;
2153 alertPreserveDims = dimensionsValueParcel;
2154 return Status::ok();
2155 }));
2156
2157 shared_ptr<MockPendingIntentRef> replaceBroadcast =
2158 SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
2159 EXPECT_CALL(*replaceBroadcast, sendSubscriberBroadcast(configUid, configId, replaceSub.id(),
2160 alertReplace.id(), _, _))
2161 .Times(0);
2162
2163 shared_ptr<MockPendingIntentRef> removeBroadcast =
2164 SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
2165 EXPECT_CALL(*removeBroadcast, sendSubscriberBroadcast(configUid, configId, removeSub.id(),
2166 alertRemove.id(), _, _))
2167 .Times(6)
2168 .WillRepeatedly(
2169 Invoke([&alertRemoveCount, &alertRemoveDims](
2170 int64_t, int64_t, int64_t, int64_t, const vector<string>&,
2171 const StatsDimensionsValueParcel& dimensionsValueParcel) {
2172 alertRemoveCount++;
2173 alertRemoveDims = dimensionsValueParcel;
2174 return Status::ok();
2175 }));
2176
2177 SubscriberReporter::getInstance().setBroadcastSubscriber(key, preserveSubId, preserveBroadcast);
2178 SubscriberReporter::getInstance().setBroadcastSubscriber(key, replaceSubId, replaceBroadcast);
2179 SubscriberReporter::getInstance().setBroadcastSubscriber(key, removeSubId, removeBroadcast);
2180
2181 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
2182 sp<StatsLogProcessor> processor = service->mProcessor;
2183 uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(TEN_MINUTES) * 1000000LL;
2184 int64_t bucketStartTimeNs = processor->mTimeBaseNs;
2185 int64_t roundedBucketStartTimeNs = bucketStartTimeNs / NS_PER_SEC * NS_PER_SEC;
2186 uint64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
2187 processor->OnConfigUpdated(bucketStartTimeNs, key, config);
2188
2189 StatsDimensionsValueParcel wlUid1 =
2190 CreateAttributionUidDimensionsValueParcel(util::WAKELOCK_STATE_CHANGED, app1Uid);
2191 StatsDimensionsValueParcel wlUid2 =
2192 CreateAttributionUidDimensionsValueParcel(util::WAKELOCK_STATE_CHANGED, app2Uid);
2193 StatsDimensionsValueParcel wlUid3 =
2194 CreateAttributionUidDimensionsValueParcel(util::WAKELOCK_STATE_CHANGED, app3Uid);
2195 StatsDimensionsValueParcel wlUid4 =
2196 CreateAttributionUidDimensionsValueParcel(util::WAKELOCK_STATE_CHANGED, app4Uid);
2197
2198 int64_t eventTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
2199 processor->OnLogEvent(
2200 CreateAcquireWakelockEvent(eventTimeNs, attributionUids1, attributionTags1, "wl1")
2201 .get(),
2202 eventTimeNs);
2203 EXPECT_EQ(alertPreserveCount, 0);
2204 EXPECT_EQ(alertRemoveCount, 0);
2205
2206 eventTimeNs = bucketStartTimeNs + 20 * NS_PER_SEC;
2207 processor->OnLogEvent(CreateScreenStateChangedEvent(
2208 eventTimeNs, android::view::DisplayStateEnum::DISPLAY_STATE_ON)
2209 .get(),
2210 eventTimeNs);
2211 EXPECT_EQ(alertPreserveCount, 0);
2212 EXPECT_EQ(alertRemoveCount, 0);
2213
2214 // Uid 1 accumulates 15 seconds in bucket #1.
2215 eventTimeNs = bucketStartTimeNs + 30 * NS_PER_SEC;
2216 processor->OnLogEvent(
2217 CreateReleaseWakelockEvent(eventTimeNs, attributionUids1, attributionTags1, "wl1")
2218 .get(),
2219 eventTimeNs);
2220 EXPECT_EQ(alertPreserveCount, 0);
2221 EXPECT_EQ(alertRemoveCount, 1);
2222 EXPECT_EQ(alertRemoveDims, wlUid1);
2223
2224 // 20 seconds accumulated in bucket #1.
2225 eventTimeNs = bucketStartTimeNs + 40 * NS_PER_SEC;
2226 processor->OnLogEvent(CreateScreenStateChangedEvent(
2227 eventTimeNs, android::view::DisplayStateEnum::DISPLAY_STATE_OFF)
2228 .get(),
2229 eventTimeNs);
2230 EXPECT_EQ(alertPreserveCount, 0);
2231 EXPECT_EQ(alertRemoveCount, 1);
2232
2233 eventTimeNs = bucket2StartTimeNs + 2 * NS_PER_SEC;
2234 processor->OnLogEvent(
2235 CreateAcquireWakelockEvent(eventTimeNs, attributionUids4, attributionTags4, "wl4")
2236 .get(),
2237 eventTimeNs);
2238 EXPECT_EQ(alertPreserveCount, 0);
2239 EXPECT_EQ(alertRemoveCount, 1);
2240
2241 eventTimeNs = bucket2StartTimeNs + 5 * NS_PER_SEC;
2242 processor->OnLogEvent(
2243 CreateAcquireWakelockEvent(eventTimeNs, attributionUids2, attributionTags2, "wl2")
2244 .get(),
2245 eventTimeNs);
2246 EXPECT_EQ(alertPreserveCount, 0);
2247 EXPECT_EQ(alertRemoveCount, 1);
2248
2249 // Alarm for alert remove for uid 4.
2250 eventTimeNs = bucket2StartTimeNs + 13 * NS_PER_SEC;
2251 processor->OnLogEvent(CreateBatteryStateChangedEvent(
2252 eventTimeNs, BatteryPluggedStateEnum::BATTERY_PLUGGED_USB)
2253 .get(),
2254 eventTimeNs);
2255 EXPECT_EQ(alertPreserveCount, 0);
2256 EXPECT_EQ(alertRemoveCount, 2);
2257 EXPECT_EQ(alertRemoveDims, wlUid4);
2258
2259 // Uid3 will be pending at the update.
2260 // Also acts as the alarm for alert remove for uid 2.
2261 eventTimeNs = bucket2StartTimeNs + 30 * NS_PER_SEC;
2262 processor->OnLogEvent(
2263 CreateAcquireWakelockEvent(eventTimeNs, attributionUids3, attributionTags3, "wl3")
2264 .get(),
2265 eventTimeNs);
2266 EXPECT_EQ(alertPreserveCount, 0);
2267 EXPECT_EQ(alertRemoveCount, 3);
2268 EXPECT_EQ(alertRemoveDims, wlUid2);
2269
2270 // Alarm for alert preserve for uid 4, enters 5 min refractory period.
2271 eventTimeNs = bucket2StartTimeNs + 33 * NS_PER_SEC;
2272 processor->OnLogEvent(CreateBatteryStateChangedEvent(
2273 eventTimeNs, BatteryPluggedStateEnum::BATTERY_PLUGGED_USB)
2274 .get(),
2275 eventTimeNs);
2276 EXPECT_EQ(alertPreserveCount, 1);
2277 EXPECT_EQ(alertPreserveDims, wlUid4);
2278 EXPECT_EQ(alertRemoveCount, 3);
2279
2280 // Uid 2 accumulates 32 seconds in partial bucket before the update. Alert preserve fires.
2281 // Preserve enters 5 min refractory for uid 2.
2282 // Alert remove fires again for uid 2 since the refractory has expired.
2283 eventTimeNs = bucket2StartTimeNs + 37 * NS_PER_SEC;
2284 processor->OnLogEvent(
2285 CreateReleaseWakelockEvent(eventTimeNs, attributionUids2, attributionTags2, "wl2")
2286 .get(),
2287 eventTimeNs);
2288 EXPECT_EQ(alertPreserveCount, 2);
2289 EXPECT_EQ(alertPreserveDims, wlUid2);
2290 EXPECT_EQ(alertRemoveCount, 4);
2291 EXPECT_EQ(alertRemoveDims, wlUid2);
2292
2293 // Alarm for alert remove for uid 3.
2294 eventTimeNs = bucket2StartTimeNs + 41 * NS_PER_SEC;
2295 processor->OnLogEvent(CreateBatteryStateChangedEvent(
2296 eventTimeNs, BatteryPluggedStateEnum::BATTERY_PLUGGED_USB)
2297 .get(),
2298 eventTimeNs);
2299 EXPECT_EQ(alertPreserveCount, 2);
2300 EXPECT_EQ(alertRemoveCount, 5);
2301 EXPECT_EQ(alertRemoveDims, wlUid3);
2302
2303 // Release wl for uid 4, has accumulated 41 seconds in partial bucket before update.
2304 // Acts as alarm for uid3 of alert remove.
2305 eventTimeNs = bucket2StartTimeNs + 43 * NS_PER_SEC;
2306 processor->OnLogEvent(
2307 CreateReleaseWakelockEvent(eventTimeNs, attributionUids4, attributionTags4, "wl4")
2308 .get(),
2309 eventTimeNs);
2310 EXPECT_EQ(alertPreserveCount, 2);
2311 EXPECT_EQ(alertRemoveCount, 6);
2312 EXPECT_EQ(alertRemoveDims, wlUid4);
2313
2314 // Starts the timer for screen on.
2315 eventTimeNs = bucket2StartTimeNs + 46 * NS_PER_SEC;
2316 processor->OnLogEvent(CreateScreenStateChangedEvent(
2317 eventTimeNs, android::view::DisplayStateEnum::DISPLAY_STATE_ON)
2318 .get(),
2319 eventTimeNs);
2320 EXPECT_EQ(alertPreserveCount, 2);
2321 EXPECT_EQ(alertRemoveCount, 6);
2322
2323 // Do config update.
2324 StatsdConfig newConfig;
2325 newConfig.add_allowed_log_source("AID_ROOT");
2326 *newConfig.add_atom_matcher() = wakelockAcquireMatcher;
2327 *newConfig.add_atom_matcher() = screenOffMatcher;
2328 *newConfig.add_atom_matcher() = wakelockReleaseMatcher;
2329 *newConfig.add_atom_matcher() = screenOnMatcher;
2330 *newConfig.add_predicate() = screenOnPredicate;
2331 *newConfig.add_predicate() = holdingWakelockPredicate;
2332 *newConfig.add_duration_metric() = durationWakelock;
2333 *newConfig.add_duration_metric() = durationScreen;
2334
2335 alertReplace.set_refractory_period_secs(2); // Causes replacement.
2336 // New alert on existing metric. Should get current full bucket, but not history of 1st bucket.
2337 Alert alertNew = createAlert("AlertNew", durationWakelock.id(), /*buckets=*/2,
2338 /*triggerSumGt=*/40 * NS_PER_SEC);
2339 *newConfig.add_alert() = alertPreserve;
2340 *newConfig.add_alert() = alertNew;
2341 *newConfig.add_alert() = alertReplace;
2342
2343 int newSubId = 4;
2344 Subscription newSub = createSubscription("S4", Subscription::ALERT, alertNew.id());
2345 newSub.mutable_broadcast_subscriber_details()->set_subscriber_id(newSubId);
2346 *newConfig.add_subscription() = newSub;
2347 *newConfig.add_subscription() = replaceSub;
2348 *newConfig.add_subscription() = preserveSub;
2349
2350 int alertNewCount = 0;
2351 StatsDimensionsValueParcel alertNewDims;
2352 shared_ptr<MockPendingIntentRef> newBroadcast =
2353 SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
2354 EXPECT_CALL(*newBroadcast,
2355 sendSubscriberBroadcast(configUid, configId, newSub.id(), alertNew.id(), _, _))
2356 .Times(3)
2357 .WillRepeatedly(
2358 Invoke([&alertNewCount, &alertNewDims](
2359 int64_t, int64_t, int64_t, int64_t, const vector<string>&,
2360 const StatsDimensionsValueParcel& dimensionsValueParcel) {
2361 alertNewCount++;
2362 alertNewDims = dimensionsValueParcel;
2363 return Status::ok();
2364 }));
2365 SubscriberReporter::getInstance().setBroadcastSubscriber(key, newSubId, newBroadcast);
2366
2367 int64_t updateTimeNs = bucket2StartTimeNs + 50 * NS_PER_SEC;
2368 processor->OnConfigUpdated(updateTimeNs, key, newConfig);
2369
2370 // Alert preserve will set alarm after the refractory period, but alert new will set it for
2371 // 8 seconds after this event.
2372 // Alert new should fire for uid 4, since it has already accumulated 41s and should fire on the
2373 // first event after the update.
2374 eventTimeNs = bucket2StartTimeNs + 55 * NS_PER_SEC;
2375 processor->OnLogEvent(
2376 CreateAcquireWakelockEvent(eventTimeNs, attributionUids2, attributionTags2, "wl2")
2377 .get(),
2378 eventTimeNs);
2379 EXPECT_EQ(alertPreserveCount, 2);
2380 EXPECT_EQ(alertNewCount, 1);
2381 EXPECT_EQ(alertNewDims, wlUid4);
2382
2383 eventTimeNs = bucket2StartTimeNs + 60 * NS_PER_SEC;
2384 // Alert replace doesn't fire because it has lost history.
2385 processor->OnLogEvent(CreateScreenStateChangedEvent(
2386 eventTimeNs, android::view::DisplayStateEnum::DISPLAY_STATE_OFF)
2387 .get(),
2388 eventTimeNs);
2389 EXPECT_EQ(alertPreserveCount, 2);
2390 EXPECT_EQ(alertNewCount, 1);
2391
2392 // Alert preserve has 15 seconds from 1st bucket, so alert should fire at bucket2Start + 80.
2393 // Serves as alarm for alert new for uid2.
2394 // Also serves as alarm for alert preserve for uid 3, which began at bucket2Start + 30.
2395 eventTimeNs = bucket2StartTimeNs + 65 * NS_PER_SEC;
2396 processor->OnLogEvent(
2397 CreateAcquireWakelockEvent(eventTimeNs, attributionUids1, attributionTags1, "wl1")
2398 .get(),
2399 eventTimeNs);
2400 EXPECT_EQ(alertPreserveCount, 3);
2401 EXPECT_EQ(alertPreserveDims, wlUid3);
2402 EXPECT_EQ(alertNewCount, 2);
2403 EXPECT_EQ(alertNewDims, wlUid2);
2404
2405 // Release wakelock for uid1, causing alert preserve to fire for uid1.
2406 // Also serves as alarm for alert new for uid3.
2407 eventTimeNs = bucket2StartTimeNs + 81 * NS_PER_SEC;
2408 processor->OnLogEvent(
2409 CreateReleaseWakelockEvent(eventTimeNs, attributionUids1, attributionTags1, "wl1")
2410 .get(),
2411 eventTimeNs);
2412 EXPECT_EQ(alertPreserveCount, 4);
2413 EXPECT_EQ(alertPreserveDims, wlUid1);
2414 EXPECT_EQ(alertNewCount, 3);
2415 EXPECT_EQ(alertNewDims, wlUid3);
2416
2417 // Clear data so it doesn't stay on disk.
2418 vector<uint8_t> buffer;
2419 processor->onDumpReport(key, bucket2StartTimeNs + 100 * NS_PER_SEC, true, true, ADB_DUMP, FAST,
2420 &buffer);
2421 SubscriberReporter::getInstance().unsetBroadcastSubscriber(key, preserveSubId);
2422 SubscriberReporter::getInstance().unsetBroadcastSubscriber(key, replaceSubId);
2423 SubscriberReporter::getInstance().unsetBroadcastSubscriber(key, removeSubId);
2424 SubscriberReporter::getInstance().unsetBroadcastSubscriber(key, newSubId);
2425 }
2426
TEST_F(ConfigUpdateE2eTest,TestAlarms)2427 TEST_F(ConfigUpdateE2eTest, TestAlarms) {
2428 StatsdConfig config;
2429 config.add_allowed_log_source("AID_ROOT");
2430 Alarm alarmPreserve = createAlarm("AlarmPreserve", /*offset*/ 5 * MS_PER_SEC,
2431 /*period*/ TimeUnitToBucketSizeInMillis(ONE_MINUTE));
2432 Alarm alarmReplace = createAlarm("AlarmReplace", /*offset*/ 1,
2433 /*period*/ TimeUnitToBucketSizeInMillis(FIVE_MINUTES));
2434 Alarm alarmRemove = createAlarm("AlarmRemove", /*offset*/ 1,
2435 /*period*/ TimeUnitToBucketSizeInMillis(ONE_MINUTE));
2436 *config.add_alarm() = alarmReplace;
2437 *config.add_alarm() = alarmPreserve;
2438 *config.add_alarm() = alarmRemove;
2439
2440 int preserveSubId = 1, replaceSubId = 2, removeSubId = 3;
2441 Subscription preserveSub = createSubscription("S1", Subscription::ALARM, alarmPreserve.id());
2442 preserveSub.mutable_broadcast_subscriber_details()->set_subscriber_id(preserveSubId);
2443 Subscription replaceSub = createSubscription("S2", Subscription::ALARM, alarmReplace.id());
2444 replaceSub.mutable_broadcast_subscriber_details()->set_subscriber_id(replaceSubId);
2445 Subscription removeSub = createSubscription("S3", Subscription::ALARM, alarmRemove.id());
2446 removeSub.mutable_broadcast_subscriber_details()->set_subscriber_id(removeSubId);
2447 *config.add_subscription() = preserveSub;
2448 *config.add_subscription() = removeSub;
2449 *config.add_subscription() = replaceSub;
2450
2451 int64_t configUid = 123, configId = 987;
2452 ConfigKey key(configUid, configId);
2453
2454 int alarmPreserveCount = 0, alarmReplaceCount = 0, alarmRemoveCount = 0;
2455
2456 // The binder calls here will happen synchronously because they are in-process.
2457 shared_ptr<MockPendingIntentRef> preserveBroadcast =
2458 SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
2459 EXPECT_CALL(*preserveBroadcast, sendSubscriberBroadcast(configUid, configId, preserveSub.id(),
2460 alarmPreserve.id(), _, _))
2461 .Times(4)
2462 .WillRepeatedly([&alarmPreserveCount](int64_t, int64_t, int64_t, int64_t,
2463 const vector<string>&,
2464 const StatsDimensionsValueParcel&) {
2465 alarmPreserveCount++;
2466 return Status::ok();
2467 });
2468
2469 shared_ptr<MockPendingIntentRef> replaceBroadcast =
2470 SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
2471 EXPECT_CALL(*replaceBroadcast, sendSubscriberBroadcast(configUid, configId, replaceSub.id(),
2472 alarmReplace.id(), _, _))
2473 .Times(2)
2474 .WillRepeatedly([&alarmReplaceCount](int64_t, int64_t, int64_t, int64_t,
2475 const vector<string>&,
2476 const StatsDimensionsValueParcel&) {
2477 alarmReplaceCount++;
2478 return Status::ok();
2479 });
2480
2481 shared_ptr<MockPendingIntentRef> removeBroadcast =
2482 SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
2483 EXPECT_CALL(*removeBroadcast, sendSubscriberBroadcast(configUid, configId, removeSub.id(),
2484 alarmRemove.id(), _, _))
2485 .Times(1)
2486 .WillRepeatedly([&alarmRemoveCount](int64_t, int64_t, int64_t, int64_t,
2487 const vector<string>&,
2488 const StatsDimensionsValueParcel&) {
2489 alarmRemoveCount++;
2490 return Status::ok();
2491 });
2492
2493 SubscriberReporter::getInstance().setBroadcastSubscriber(key, preserveSubId, preserveBroadcast);
2494 SubscriberReporter::getInstance().setBroadcastSubscriber(key, replaceSubId, replaceBroadcast);
2495 SubscriberReporter::getInstance().setBroadcastSubscriber(key, removeSubId, removeBroadcast);
2496
2497 int64_t startTimeSec = 10;
2498 sp<StatsLogProcessor> processor = CreateStatsLogProcessor(
2499 startTimeSec * NS_PER_SEC, startTimeSec * NS_PER_SEC, config, key);
2500
2501 sp<AlarmMonitor> alarmMonitor = processor->getPeriodicAlarmMonitor();
2502 // First alarm is for alarm preserve's offset of 5 seconds.
2503 EXPECT_EQ(alarmMonitor->getRegisteredAlarmTimeSec(), startTimeSec + 5);
2504
2505 // Alarm fired at 5. AlarmPreserve should fire.
2506 int32_t alarmFiredTimestampSec = startTimeSec + 5;
2507 auto alarmSet = alarmMonitor->popSoonerThan(static_cast<uint32_t>(alarmFiredTimestampSec));
2508 processor->onPeriodicAlarmFired(alarmFiredTimestampSec * NS_PER_SEC, alarmSet);
2509 EXPECT_EQ(alarmPreserveCount, 1);
2510 EXPECT_EQ(alarmReplaceCount, 0);
2511 EXPECT_EQ(alarmRemoveCount, 0);
2512 EXPECT_EQ(alarmMonitor->getRegisteredAlarmTimeSec(), startTimeSec + 60);
2513
2514 // Alarm fired at 75. AlarmPreserve and AlarmRemove should fire.
2515 alarmFiredTimestampSec = startTimeSec + 75;
2516 alarmSet = alarmMonitor->popSoonerThan(static_cast<uint32_t>(alarmFiredTimestampSec));
2517 processor->onPeriodicAlarmFired(alarmFiredTimestampSec * NS_PER_SEC, alarmSet);
2518 EXPECT_EQ(alarmPreserveCount, 2);
2519 EXPECT_EQ(alarmReplaceCount, 0);
2520 EXPECT_EQ(alarmRemoveCount, 1);
2521 EXPECT_EQ(alarmMonitor->getRegisteredAlarmTimeSec(), startTimeSec + 120);
2522
2523 // Do config update.
2524 StatsdConfig newConfig;
2525 newConfig.add_allowed_log_source("AID_ROOT");
2526
2527 // Change alarm replace's definition.
2528 alarmReplace.set_period_millis(TimeUnitToBucketSizeInMillis(ONE_MINUTE));
2529 Alarm alarmNew = createAlarm("AlarmNew", /*offset*/ 1,
2530 /*period*/ TimeUnitToBucketSizeInMillis(FIVE_MINUTES));
2531 *newConfig.add_alarm() = alarmNew;
2532 *newConfig.add_alarm() = alarmPreserve;
2533 *newConfig.add_alarm() = alarmReplace;
2534
2535 int newSubId = 4;
2536 Subscription newSub = createSubscription("S4", Subscription::ALARM, alarmNew.id());
2537 newSub.mutable_broadcast_subscriber_details()->set_subscriber_id(newSubId);
2538 *newConfig.add_subscription() = newSub;
2539 *newConfig.add_subscription() = replaceSub;
2540 *newConfig.add_subscription() = preserveSub;
2541
2542 int alarmNewCount = 0;
2543 shared_ptr<MockPendingIntentRef> newBroadcast =
2544 SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
2545 EXPECT_CALL(*newBroadcast,
2546 sendSubscriberBroadcast(configUid, configId, newSub.id(), alarmNew.id(), _, _))
2547 .Times(1)
2548 .WillRepeatedly([&alarmNewCount](int64_t, int64_t, int64_t, int64_t,
2549 const vector<string>&,
2550 const StatsDimensionsValueParcel&) {
2551 alarmNewCount++;
2552 return Status::ok();
2553 });
2554 SubscriberReporter::getInstance().setBroadcastSubscriber(key, newSubId, newBroadcast);
2555
2556 processor->OnConfigUpdated((startTimeSec + 90) * NS_PER_SEC, key, newConfig);
2557 // After the update, the alarm time should remain unchanged since alarm replace now fires every
2558 // minute with no offset.
2559 EXPECT_EQ(alarmMonitor->getRegisteredAlarmTimeSec(), startTimeSec + 120);
2560
2561 // Alarm fired at 120. AlermReplace should fire.
2562 alarmFiredTimestampSec = startTimeSec + 120;
2563 alarmSet = alarmMonitor->popSoonerThan(static_cast<uint32_t>(alarmFiredTimestampSec));
2564 processor->onPeriodicAlarmFired(alarmFiredTimestampSec * NS_PER_SEC, alarmSet);
2565 EXPECT_EQ(alarmPreserveCount, 2);
2566 EXPECT_EQ(alarmReplaceCount, 1);
2567 EXPECT_EQ(alarmNewCount, 0);
2568 EXPECT_EQ(alarmMonitor->getRegisteredAlarmTimeSec(), startTimeSec + 125);
2569
2570 // Alarm fired at 130. AlarmPreserve should fire.
2571 alarmFiredTimestampSec = startTimeSec + 130;
2572 alarmSet = alarmMonitor->popSoonerThan(static_cast<uint32_t>(alarmFiredTimestampSec));
2573 processor->onPeriodicAlarmFired(alarmFiredTimestampSec * NS_PER_SEC, alarmSet);
2574 EXPECT_EQ(alarmPreserveCount, 3);
2575 EXPECT_EQ(alarmReplaceCount, 1);
2576 EXPECT_EQ(alarmNewCount, 0);
2577 EXPECT_EQ(alarmMonitor->getRegisteredAlarmTimeSec(), startTimeSec + 180);
2578
2579 // Alarm fired late at 310. All alerms should fire.
2580 alarmFiredTimestampSec = startTimeSec + 310;
2581 alarmSet = alarmMonitor->popSoonerThan(static_cast<uint32_t>(alarmFiredTimestampSec));
2582 processor->onPeriodicAlarmFired(alarmFiredTimestampSec * NS_PER_SEC, alarmSet);
2583 EXPECT_EQ(alarmPreserveCount, 4);
2584 EXPECT_EQ(alarmReplaceCount, 2);
2585 EXPECT_EQ(alarmNewCount, 1);
2586 EXPECT_EQ(alarmMonitor->getRegisteredAlarmTimeSec(), startTimeSec + 360);
2587
2588 // Clear subscribers
2589 SubscriberReporter::getInstance().unsetBroadcastSubscriber(key, preserveSubId);
2590 SubscriberReporter::getInstance().unsetBroadcastSubscriber(key, replaceSubId);
2591 SubscriberReporter::getInstance().unsetBroadcastSubscriber(key, removeSubId);
2592 SubscriberReporter::getInstance().unsetBroadcastSubscriber(key, newSubId);
2593 }
2594
TEST_F(ConfigUpdateE2eTest,TestNewDurationExistingWhat)2595 TEST_F(ConfigUpdateE2eTest, TestNewDurationExistingWhat) {
2596 StatsdConfig config;
2597 config.add_allowed_log_source("AID_ROOT");
2598 *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
2599 *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
2600
2601 Predicate holdingWakelockPredicate = CreateHoldingWakelockPredicate();
2602 *config.add_predicate() = holdingWakelockPredicate;
2603
2604 ConfigKey key(123, 987);
2605 uint64_t bucketStartTimeNs = 10000000000; // 0:10
2606 uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(FIVE_MINUTES) * 1000000LL;
2607 sp<StatsLogProcessor> processor =
2608 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, key);
2609
2610 int app1Uid = 123;
2611 vector<int> attributionUids1 = {app1Uid};
2612 vector<string> attributionTags1 = {"App1"};
2613 // Create a wakelock acquire, causing the condition to be true.
2614 unique_ptr<LogEvent> event = CreateAcquireWakelockEvent(bucketStartTimeNs + 10 * NS_PER_SEC,
2615 attributionUids1, attributionTags1,
2616 "wl1"); // 0:10
2617 processor->OnLogEvent(event.get());
2618
2619 // Add metric.
2620 DurationMetric* durationMetric = config.add_duration_metric();
2621 durationMetric->set_id(StringToId("WakelockDuration"));
2622 durationMetric->set_what(holdingWakelockPredicate.id());
2623 durationMetric->set_aggregation_type(DurationMetric::SUM);
2624 durationMetric->set_bucket(FIVE_MINUTES);
2625
2626 uint64_t updateTimeNs = bucketStartTimeNs + 60 * NS_PER_SEC; // 1:00
2627 processor->OnConfigUpdated(updateTimeNs, key, config);
2628
2629 event = CreateReleaseWakelockEvent(bucketStartTimeNs + 80 * NS_PER_SEC, attributionUids1,
2630 attributionTags1,
2631 "wl1"); // 1:20
2632 processor->OnLogEvent(event.get());
2633 uint64_t dumpTimeNs = bucketStartTimeNs + 90 * NS_PER_SEC; // 1:30
2634 ConfigMetricsReportList reports;
2635 vector<uint8_t> buffer;
2636 processor->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, FAST, &buffer);
2637 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
2638 backfillDimensionPath(&reports);
2639 backfillStringInReport(&reports);
2640 backfillStartEndTimestamp(&reports);
2641 ASSERT_EQ(reports.reports_size(), 1);
2642 ASSERT_EQ(reports.reports(0).metrics_size(), 1);
2643 EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
2644
2645 StatsLogReport::DurationMetricDataWrapper metricData;
2646 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(), &metricData);
2647 ASSERT_EQ(metricData.data_size(), 1);
2648 DurationMetricData data = metricData.data(0);
2649 ASSERT_EQ(data.bucket_info_size(), 1);
2650
2651 DurationBucketInfo bucketInfo = data.bucket_info(0);
2652 EXPECT_EQ(bucketInfo.start_bucket_elapsed_nanos(), updateTimeNs);
2653 EXPECT_EQ(bucketInfo.end_bucket_elapsed_nanos(), dumpTimeNs);
2654 EXPECT_EQ(bucketInfo.duration_nanos(), 20 * NS_PER_SEC);
2655 }
2656
TEST_F(ConfigUpdateE2eTest,TestNewDurationExistingWhatSlicedCondition)2657 TEST_F(ConfigUpdateE2eTest, TestNewDurationExistingWhatSlicedCondition) {
2658 StatsdConfig config;
2659 config.add_allowed_log_source("AID_ROOT");
2660 *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
2661 *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
2662 *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
2663 *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
2664
2665 Predicate holdingWakelockPredicate = CreateHoldingWakelockPredicate();
2666 // The predicate is dimensioning by first attribution node by uid.
2667 *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() =
2668 CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
2669 *config.add_predicate() = holdingWakelockPredicate;
2670
2671 Predicate isInBackgroundPredicate = CreateIsInBackgroundPredicate();
2672 *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
2673 CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /*uid*/});
2674 *config.add_predicate() = isInBackgroundPredicate;
2675
2676 ConfigKey key(123, 987);
2677 uint64_t bucketStartTimeNs = 10000000000; // 0:10
2678 uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(FIVE_MINUTES) * 1000000LL;
2679 sp<StatsLogProcessor> processor =
2680 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, key);
2681
2682 int app1Uid = 123, app2Uid = 456;
2683 vector<int> attributionUids1 = {app1Uid};
2684 vector<string> attributionTags1 = {"App1"};
2685 vector<int> attributionUids2 = {app2Uid};
2686 vector<string> attributionTags2 = {"App2"};
2687 unique_ptr<LogEvent> event = CreateAcquireWakelockEvent(bucketStartTimeNs + 10 * NS_PER_SEC,
2688 attributionUids1, attributionTags1,
2689 "wl1"); // 0:10
2690 processor->OnLogEvent(event.get());
2691 event = CreateMoveToBackgroundEvent(bucketStartTimeNs + 22 * NS_PER_SEC, app1Uid); // 0:22
2692 processor->OnLogEvent(event.get());
2693 event = CreateAcquireWakelockEvent(bucketStartTimeNs + 35 * NS_PER_SEC, attributionUids2,
2694 attributionTags2,
2695 "wl1"); // 0:35
2696 processor->OnLogEvent(event.get());
2697
2698 // Add metric.
2699 DurationMetric* durationMetric = config.add_duration_metric();
2700 durationMetric->set_id(StringToId("WakelockDuration"));
2701 durationMetric->set_what(holdingWakelockPredicate.id());
2702 durationMetric->set_condition(isInBackgroundPredicate.id());
2703 durationMetric->set_aggregation_type(DurationMetric::SUM);
2704 // The metric is dimensioning by first attribution node and only by uid.
2705 *durationMetric->mutable_dimensions_in_what() =
2706 CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
2707 durationMetric->set_bucket(FIVE_MINUTES);
2708 // Links between wakelock state atom and condition of app is in background.
2709 auto links = durationMetric->add_links();
2710 links->set_condition(isInBackgroundPredicate.id());
2711 *links->mutable_fields_in_what() =
2712 CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
2713 *links->mutable_fields_in_condition() =
2714 CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /*uid*/});
2715
2716 uint64_t updateTimeNs = bucketStartTimeNs + 60 * NS_PER_SEC; // 1:00
2717 processor->OnConfigUpdated(updateTimeNs, key, config);
2718
2719 event = CreateMoveToBackgroundEvent(bucketStartTimeNs + 73 * NS_PER_SEC, app2Uid); // 1:13
2720 processor->OnLogEvent(event.get());
2721 event = CreateReleaseWakelockEvent(bucketStartTimeNs + 84 * NS_PER_SEC, attributionUids1,
2722 attributionTags1, "wl1"); // 1:24
2723 processor->OnLogEvent(event.get());
2724
2725 uint64_t dumpTimeNs = bucketStartTimeNs + 90 * NS_PER_SEC; // 1:30
2726 ConfigMetricsReportList reports;
2727 vector<uint8_t> buffer;
2728 processor->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, FAST, &buffer);
2729 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
2730 backfillDimensionPath(&reports);
2731 backfillStringInReport(&reports);
2732 backfillStartEndTimestamp(&reports);
2733 ASSERT_EQ(reports.reports_size(), 1);
2734 ASSERT_EQ(reports.reports(0).metrics_size(), 1);
2735 EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
2736
2737 StatsLogReport::DurationMetricDataWrapper metricData;
2738 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(), &metricData);
2739 ASSERT_EQ(metricData.data_size(), 2);
2740
2741 DurationMetricData data = metricData.data(0);
2742 ValidateAttributionUidDimension(data.dimensions_in_what(), util::WAKELOCK_STATE_CHANGED,
2743 app1Uid);
2744 ASSERT_EQ(data.bucket_info_size(), 1);
2745 DurationBucketInfo bucketInfo = data.bucket_info(0);
2746 EXPECT_EQ(bucketInfo.duration_nanos(), 24 * NS_PER_SEC);
2747
2748 data = metricData.data(1);
2749 ValidateAttributionUidDimension(data.dimensions_in_what(), util::WAKELOCK_STATE_CHANGED,
2750 app2Uid);
2751 ASSERT_EQ(data.bucket_info_size(), 1);
2752 bucketInfo = data.bucket_info(0);
2753 EXPECT_EQ(bucketInfo.duration_nanos(), 17 * NS_PER_SEC);
2754 }
2755
TEST_F(ConfigUpdateE2eTest,TestNewDurationExistingWhatSlicedState)2756 TEST_F(ConfigUpdateE2eTest, TestNewDurationExistingWhatSlicedState) {
2757 StatsdConfig config;
2758 config.add_allowed_log_source("AID_ROOT");
2759 *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
2760 *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
2761
2762 Predicate holdingWakelockPredicate = CreateHoldingWakelockPredicate();
2763 // The predicate is dimensioning by first attribution node by uid.
2764 *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() =
2765 CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
2766 *config.add_predicate() = holdingWakelockPredicate;
2767
2768 auto uidProcessState = CreateUidProcessState();
2769 *config.add_state() = uidProcessState;
2770
2771 // Count metric. We don't care about this one. Only use it so the StateTracker gets persisted.
2772 CountMetric* countMetric = config.add_count_metric();
2773 countMetric->set_id(StringToId("Tmp"));
2774 countMetric->set_what(config.atom_matcher(0).id());
2775 countMetric->add_slice_by_state(uidProcessState.id());
2776 // The metric is dimensioning by first attribution node and only by uid.
2777 *countMetric->mutable_dimensions_in_what() =
2778 CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
2779 countMetric->set_bucket(FIVE_MINUTES);
2780 auto stateLink = countMetric->add_state_link();
2781 stateLink->set_state_atom_id(util::UID_PROCESS_STATE_CHANGED);
2782 *stateLink->mutable_fields_in_what() =
2783 CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
2784 *stateLink->mutable_fields_in_state() =
2785 CreateDimensions(util::UID_PROCESS_STATE_CHANGED, {1 /*uid*/});
2786 config.add_no_report_metric(countMetric->id());
2787
2788 ConfigKey key(123, 987);
2789 uint64_t bucketStartTimeNs = 10000000000; // 0:10
2790 uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(FIVE_MINUTES) * 1000000LL;
2791 sp<StatsLogProcessor> processor =
2792 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, key);
2793
2794 int app1Uid = 123, app2Uid = 456;
2795 vector<int> attributionUids1 = {app1Uid};
2796 vector<string> attributionTags1 = {"App1"};
2797 vector<int> attributionUids2 = {app2Uid};
2798 vector<string> attributionTags2 = {"App2"};
2799 unique_ptr<LogEvent> event = CreateUidProcessStateChangedEvent(
2800 bucketStartTimeNs + 10 * NS_PER_SEC, app1Uid,
2801 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND); // 0:10
2802 processor->OnLogEvent(event.get());
2803 event = CreateAcquireWakelockEvent(bucketStartTimeNs + 22 * NS_PER_SEC, attributionUids1,
2804 attributionTags1,
2805 "wl1"); // 0:22
2806 processor->OnLogEvent(event.get());
2807 event = CreateUidProcessStateChangedEvent(
2808 bucketStartTimeNs + 30 * NS_PER_SEC, app2Uid,
2809 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND); // 0:30
2810 processor->OnLogEvent(event.get());
2811
2812 // Add metric.
2813 DurationMetric* durationMetric = config.add_duration_metric();
2814 durationMetric->set_id(StringToId("WakelockDuration"));
2815 durationMetric->set_what(holdingWakelockPredicate.id());
2816 durationMetric->add_slice_by_state(uidProcessState.id());
2817 durationMetric->set_aggregation_type(DurationMetric::SUM);
2818 // The metric is dimensioning by first attribution node and only by uid.
2819 *durationMetric->mutable_dimensions_in_what() =
2820 CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
2821 durationMetric->set_bucket(FIVE_MINUTES);
2822 // Links between wakelock state atom and condition of app is in background.
2823 stateLink = durationMetric->add_state_link();
2824 stateLink->set_state_atom_id(util::UID_PROCESS_STATE_CHANGED);
2825 *stateLink->mutable_fields_in_what() =
2826 CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
2827 *stateLink->mutable_fields_in_state() =
2828 CreateDimensions(util::UID_PROCESS_STATE_CHANGED, {1 /*uid*/});
2829
2830 uint64_t updateTimeNs = bucketStartTimeNs + 60 * NS_PER_SEC; // 1:00
2831 processor->OnConfigUpdated(updateTimeNs, key, config);
2832
2833 event = CreateAcquireWakelockEvent(bucketStartTimeNs + 72 * NS_PER_SEC, attributionUids2,
2834 attributionTags2,
2835 "wl1"); // 1:13
2836 processor->OnLogEvent(event.get());
2837 event = CreateUidProcessStateChangedEvent(
2838 bucketStartTimeNs + 75 * NS_PER_SEC, app1Uid,
2839 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND); // 1:15
2840 processor->OnLogEvent(event.get());
2841 event = CreateReleaseWakelockEvent(bucketStartTimeNs + 84 * NS_PER_SEC, attributionUids1,
2842 attributionTags1, "wl1"); // 1:24
2843 processor->OnLogEvent(event.get());
2844
2845 uint64_t dumpTimeNs = bucketStartTimeNs + 90 * NS_PER_SEC; // 1:30
2846 ConfigMetricsReportList reports;
2847 vector<uint8_t> buffer;
2848 processor->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, FAST, &buffer);
2849 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
2850 backfillDimensionPath(&reports);
2851 backfillStringInReport(&reports);
2852 backfillStartEndTimestamp(&reports);
2853 ASSERT_EQ(reports.reports_size(), 1);
2854 ASSERT_EQ(reports.reports(0).metrics_size(), 1);
2855 EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
2856
2857 StatsLogReport::DurationMetricDataWrapper metricData;
2858 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(), &metricData);
2859 ASSERT_EQ(metricData.data_size(), 3);
2860
2861 DurationMetricData data = metricData.data(0);
2862 ValidateAttributionUidDimension(data.dimensions_in_what(), util::WAKELOCK_STATE_CHANGED,
2863 app1Uid);
2864 ValidateStateValue(data.slice_by_state(), util::UID_PROCESS_STATE_CHANGED,
2865 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND);
2866 ASSERT_EQ(data.bucket_info_size(), 1);
2867 DurationBucketInfo bucketInfo = data.bucket_info(0);
2868 EXPECT_EQ(bucketInfo.duration_nanos(), 15 * NS_PER_SEC);
2869
2870 data = metricData.data(1);
2871 ValidateAttributionUidDimension(data.dimensions_in_what(), util::WAKELOCK_STATE_CHANGED,
2872 app1Uid);
2873 ValidateStateValue(data.slice_by_state(), util::UID_PROCESS_STATE_CHANGED,
2874 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND);
2875 ASSERT_EQ(data.bucket_info_size(), 1);
2876 bucketInfo = data.bucket_info(0);
2877 EXPECT_EQ(bucketInfo.duration_nanos(), 9 * NS_PER_SEC);
2878
2879 data = metricData.data(2);
2880 ValidateAttributionUidDimension(data.dimensions_in_what(), util::WAKELOCK_STATE_CHANGED,
2881 app2Uid);
2882 ValidateStateValue(data.slice_by_state(), util::UID_PROCESS_STATE_CHANGED,
2883 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND);
2884 ASSERT_EQ(data.bucket_info_size(), 1);
2885 bucketInfo = data.bucket_info(0);
2886 EXPECT_EQ(bucketInfo.duration_nanos(), 18 * NS_PER_SEC);
2887 }
2888
2889 #else
2890 GTEST_LOG_(INFO) << "This test does nothing.\n";
2891 #endif
2892
2893 } // namespace statsd
2894 } // namespace os
2895 } // namespace android
2896