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