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