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