blob: 88aa1800c75a45134e20ba6605bd69d78cd11af1 [file] [log] [blame]
David Chend9269e22017-12-05 13:43:51 -08001// Copyright (C) 2017 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 "StatsLogProcessor.h"
16#include "config/ConfigKey.h"
David Chen35045cb2018-03-23 22:21:47 -070017#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
David Chend9269e22017-12-05 13:43:51 -080018#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
19#include "guardrail/StatsdStats.h"
20#include "logd/LogEvent.h"
21#include "packages/UidMap.h"
22#include "statslog.h"
23
24#include <gmock/gmock.h>
25#include <gtest/gtest.h>
26
David Chen9e6dbbd2018-05-07 17:52:29 -070027#include "tests/statsd_test_util.h"
28
David Chend9269e22017-12-05 13:43:51 -080029#include <stdio.h>
30
31using namespace android;
32using namespace testing;
33
34namespace android {
35namespace os {
36namespace statsd {
37
Yao Chen288c6002017-12-12 13:43:18 -080038using android::util::ProtoOutputStream;
39
David Chend9269e22017-12-05 13:43:51 -080040#ifdef __ANDROID__
41
42/**
43 * Mock MetricsManager (ByteSize() is called).
44 */
45class MockMetricsManager : public MetricsManager {
46public:
Chenjie Yue2219202018-06-08 10:07:51 -070047 MockMetricsManager()
48 : MetricsManager(ConfigKey(1, 12345), StatsdConfig(), 1000, 1000, new UidMap(),
49 new StatsPullerManager(),
50 new AlarmMonitor(10, [](const sp<IStatsCompanionService>&, int64_t) {},
51 [](const sp<IStatsCompanionService>&) {}),
52 new AlarmMonitor(10, [](const sp<IStatsCompanionService>&, int64_t) {},
53 [](const sp<IStatsCompanionService>&) {})) {
David Chend9269e22017-12-05 13:43:51 -080054 }
55
56 MOCK_METHOD0(byteSize, size_t());
Yao Chen06dba5d2018-01-26 13:38:16 -080057
Yangster-macb142cc82018-03-30 15:22:08 -070058 MOCK_METHOD1(dropData, void(const int64_t dropTimeNs));
David Chend9269e22017-12-05 13:43:51 -080059};
60
61TEST(StatsLogProcessorTest, TestRateLimitByteSize) {
62 sp<UidMap> m = new UidMap();
Chenjie Yue2219202018-06-08 10:07:51 -070063 sp<StatsPullerManager> pullerManager = new StatsPullerManager();
Yangster-mac932ecec2018-02-01 10:23:52 -080064 sp<AlarmMonitor> anomalyAlarmMonitor;
65 sp<AlarmMonitor> periodicAlarmMonitor;
David Chend9269e22017-12-05 13:43:51 -080066 // Construct the processor with a dummy sendBroadcast function that does nothing.
Chenjie Yue2219202018-06-08 10:07:51 -070067 StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, 0,
Tej Singh6ede28b2019-01-29 17:06:54 -080068 [](const ConfigKey& key) { return true; },
69 [](const int&, const vector<int64_t>&) {return true;});
David Chend9269e22017-12-05 13:43:51 -080070
71 MockMetricsManager mockMetricsManager;
72
Yangster-mac94e197c2018-01-02 16:03:03 -080073 ConfigKey key(100, 12345);
David Chend9269e22017-12-05 13:43:51 -080074 // Expect only the first flush to trigger a check for byte size since the last two are
75 // rate-limited.
76 EXPECT_CALL(mockMetricsManager, byteSize()).Times(1);
Yangster-macb0d06282018-01-05 15:44:07 -080077 p.flushIfNecessaryLocked(99, key, mockMetricsManager);
78 p.flushIfNecessaryLocked(100, key, mockMetricsManager);
79 p.flushIfNecessaryLocked(101, key, mockMetricsManager);
David Chend9269e22017-12-05 13:43:51 -080080}
81
82TEST(StatsLogProcessorTest, TestRateLimitBroadcast) {
83 sp<UidMap> m = new UidMap();
Chenjie Yue2219202018-06-08 10:07:51 -070084 sp<StatsPullerManager> pullerManager = new StatsPullerManager();
Yangster-mac932ecec2018-02-01 10:23:52 -080085 sp<AlarmMonitor> anomalyAlarmMonitor;
86 sp<AlarmMonitor> subscriberAlarmMonitor;
David Chend9269e22017-12-05 13:43:51 -080087 int broadcastCount = 0;
Chenjie Yue2219202018-06-08 10:07:51 -070088 StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
89 [&broadcastCount](const ConfigKey& key) {
90 broadcastCount++;
91 return true;
Tej Singh6ede28b2019-01-29 17:06:54 -080092 },
93 [](const int&, const vector<int64_t>&) {return true;});
David Chend9269e22017-12-05 13:43:51 -080094
95 MockMetricsManager mockMetricsManager;
96
Yangster-mac94e197c2018-01-02 16:03:03 -080097 ConfigKey key(100, 12345);
David Chend9269e22017-12-05 13:43:51 -080098 EXPECT_CALL(mockMetricsManager, byteSize())
Yao Chen8a8d16c2018-02-08 14:50:40 -080099 .Times(1)
David Chend9269e22017-12-05 13:43:51 -0800100 .WillRepeatedly(Return(int(StatsdStats::kMaxMetricsBytesPerConfig * .95)));
101
102 // Expect only one broadcast despite always returning a size that should trigger broadcast.
Yangster-macb0d06282018-01-05 15:44:07 -0800103 p.flushIfNecessaryLocked(1, key, mockMetricsManager);
David Chend9269e22017-12-05 13:43:51 -0800104 EXPECT_EQ(1, broadcastCount);
105
Yao Chen8a8d16c2018-02-08 14:50:40 -0800106 // b/73089712
David Chend9269e22017-12-05 13:43:51 -0800107 // This next call to flush should not trigger a broadcast.
Yao Chen8a8d16c2018-02-08 14:50:40 -0800108 // p.mLastByteSizeTimes.clear(); // Force another check for byte size.
109 // p.flushIfNecessaryLocked(2, key, mockMetricsManager);
110 // EXPECT_EQ(1, broadcastCount);
David Chend9269e22017-12-05 13:43:51 -0800111}
112
113TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge) {
114 sp<UidMap> m = new UidMap();
Chenjie Yue2219202018-06-08 10:07:51 -0700115 sp<StatsPullerManager> pullerManager = new StatsPullerManager();
Yangster-mac932ecec2018-02-01 10:23:52 -0800116 sp<AlarmMonitor> anomalyAlarmMonitor;
117 sp<AlarmMonitor> subscriberAlarmMonitor;
David Chend9269e22017-12-05 13:43:51 -0800118 int broadcastCount = 0;
Chenjie Yue2219202018-06-08 10:07:51 -0700119 StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
120 [&broadcastCount](const ConfigKey& key) {
121 broadcastCount++;
122 return true;
Tej Singh6ede28b2019-01-29 17:06:54 -0800123 },
124 [](const int&, const vector<int64_t>&) {return true;});
David Chend9269e22017-12-05 13:43:51 -0800125
126 MockMetricsManager mockMetricsManager;
127
Yangster-mac94e197c2018-01-02 16:03:03 -0800128 ConfigKey key(100, 12345);
David Chend9269e22017-12-05 13:43:51 -0800129 EXPECT_CALL(mockMetricsManager, byteSize())
130 .Times(1)
131 .WillRepeatedly(Return(int(StatsdStats::kMaxMetricsBytesPerConfig * 1.2)));
132
Yao Chen06dba5d2018-01-26 13:38:16 -0800133 EXPECT_CALL(mockMetricsManager, dropData(_)).Times(1);
David Chend9269e22017-12-05 13:43:51 -0800134
135 // Expect to call the onDumpReport and skip the broadcast.
Yangster-macb0d06282018-01-05 15:44:07 -0800136 p.flushIfNecessaryLocked(1, key, mockMetricsManager);
David Chend9269e22017-12-05 13:43:51 -0800137 EXPECT_EQ(0, broadcastCount);
138}
139
David Chen9e6dbbd2018-05-07 17:52:29 -0700140StatsdConfig MakeConfig(bool includeMetric) {
141 StatsdConfig config;
142 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
143
144 if (includeMetric) {
145 auto appCrashMatcher = CreateProcessCrashAtomMatcher();
146 *config.add_atom_matcher() = appCrashMatcher;
147 auto countMetric = config.add_count_metric();
148 countMetric->set_id(StringToId("AppCrashes"));
149 countMetric->set_what(appCrashMatcher.id());
150 countMetric->set_bucket(FIVE_MINUTES);
151 }
152 return config;
153}
154
David Chen35045cb2018-03-23 22:21:47 -0700155TEST(StatsLogProcessorTest, TestUidMapHasSnapshot) {
156 // Setup simple config key corresponding to empty config.
157 sp<UidMap> m = new UidMap();
Chenjie Yue2219202018-06-08 10:07:51 -0700158 sp<StatsPullerManager> pullerManager = new StatsPullerManager();
dwchen730403e2018-10-29 11:41:56 -0700159 m->updateMap(1, {1, 2}, {1, 2}, {String16("v1"), String16("v2")},
160 {String16("p1"), String16("p2")}, {String16(""), String16("")});
David Chen35045cb2018-03-23 22:21:47 -0700161 sp<AlarmMonitor> anomalyAlarmMonitor;
162 sp<AlarmMonitor> subscriberAlarmMonitor;
163 int broadcastCount = 0;
Chenjie Yue2219202018-06-08 10:07:51 -0700164 StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
165 [&broadcastCount](const ConfigKey& key) {
166 broadcastCount++;
167 return true;
Tej Singh6ede28b2019-01-29 17:06:54 -0800168 },
169 [](const int&, const vector<int64_t>&) {return true;});
David Chen35045cb2018-03-23 22:21:47 -0700170 ConfigKey key(3, 4);
David Chen9e6dbbd2018-05-07 17:52:29 -0700171 StatsdConfig config = MakeConfig(true);
Yangster-macc04feba2018-04-02 14:37:33 -0700172 p.OnConfigUpdated(0, key, config);
David Chen35045cb2018-03-23 22:21:47 -0700173
174 // Expect to get no metrics, but snapshot specified above in uidmap.
175 vector<uint8_t> bytes;
Olivier Gaillard6c75ecd2019-02-20 09:57:33 +0000176 p.onDumpReport(key, 1, false, true, ADB_DUMP, FAST, &bytes);
David Chen35045cb2018-03-23 22:21:47 -0700177
178 ConfigMetricsReportList output;
179 output.ParseFromArray(bytes.data(), bytes.size());
180 EXPECT_TRUE(output.reports_size() > 0);
181 auto uidmap = output.reports(0).uid_map();
182 EXPECT_TRUE(uidmap.snapshots_size() > 0);
183 EXPECT_EQ(2, uidmap.snapshots(0).package_info_size());
184}
185
David Chen9e6dbbd2018-05-07 17:52:29 -0700186TEST(StatsLogProcessorTest, TestEmptyConfigHasNoUidMap) {
187 // Setup simple config key corresponding to empty config.
188 sp<UidMap> m = new UidMap();
Chenjie Yue2219202018-06-08 10:07:51 -0700189 sp<StatsPullerManager> pullerManager = new StatsPullerManager();
dwchen730403e2018-10-29 11:41:56 -0700190 m->updateMap(1, {1, 2}, {1, 2}, {String16("v1"), String16("v2")},
191 {String16("p1"), String16("p2")}, {String16(""), String16("")});
David Chen9e6dbbd2018-05-07 17:52:29 -0700192 sp<AlarmMonitor> anomalyAlarmMonitor;
193 sp<AlarmMonitor> subscriberAlarmMonitor;
194 int broadcastCount = 0;
Chenjie Yue2219202018-06-08 10:07:51 -0700195 StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
196 [&broadcastCount](const ConfigKey& key) {
197 broadcastCount++;
198 return true;
Tej Singh6ede28b2019-01-29 17:06:54 -0800199 },
200 [](const int&, const vector<int64_t>&) {return true;});
David Chen9e6dbbd2018-05-07 17:52:29 -0700201 ConfigKey key(3, 4);
202 StatsdConfig config = MakeConfig(false);
203 p.OnConfigUpdated(0, key, config);
204
205 // Expect to get no metrics, but snapshot specified above in uidmap.
206 vector<uint8_t> bytes;
Olivier Gaillard6c75ecd2019-02-20 09:57:33 +0000207 p.onDumpReport(key, 1, false, true, ADB_DUMP, FAST, &bytes);
David Chen9e6dbbd2018-05-07 17:52:29 -0700208
209 ConfigMetricsReportList output;
210 output.ParseFromArray(bytes.data(), bytes.size());
211 EXPECT_TRUE(output.reports_size() > 0);
212 EXPECT_FALSE(output.reports(0).has_uid_map());
213}
214
David Chenfaa1af52018-03-30 15:14:04 -0700215TEST(StatsLogProcessorTest, TestReportIncludesSubConfig) {
216 // Setup simple config key corresponding to empty config.
217 sp<UidMap> m = new UidMap();
Chenjie Yue2219202018-06-08 10:07:51 -0700218 sp<StatsPullerManager> pullerManager = new StatsPullerManager();
David Chenfaa1af52018-03-30 15:14:04 -0700219 sp<AlarmMonitor> anomalyAlarmMonitor;
220 sp<AlarmMonitor> subscriberAlarmMonitor;
221 int broadcastCount = 0;
Chenjie Yue2219202018-06-08 10:07:51 -0700222 StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
223 [&broadcastCount](const ConfigKey& key) {
224 broadcastCount++;
225 return true;
Tej Singh6ede28b2019-01-29 17:06:54 -0800226 },
227 [](const int&, const vector<int64_t>&) {return true;});
David Chenfaa1af52018-03-30 15:14:04 -0700228 ConfigKey key(3, 4);
229 StatsdConfig config;
230 auto annotation = config.add_annotation();
231 annotation->set_field_int64(1);
232 annotation->set_field_int32(2);
233 config.add_allowed_log_source("AID_ROOT");
234 p.OnConfigUpdated(1, key, config);
235
236 // Expect to get no metrics, but snapshot specified above in uidmap.
237 vector<uint8_t> bytes;
Olivier Gaillard6c75ecd2019-02-20 09:57:33 +0000238 p.onDumpReport(key, 1, false, true, ADB_DUMP, FAST, &bytes);
David Chenfaa1af52018-03-30 15:14:04 -0700239
240 ConfigMetricsReportList output;
241 output.ParseFromArray(bytes.data(), bytes.size());
242 EXPECT_TRUE(output.reports_size() > 0);
243 auto report = output.reports(0);
244 EXPECT_EQ(1, report.annotation_size());
245 EXPECT_EQ(1, report.annotation(0).field_int64());
246 EXPECT_EQ(2, report.annotation(0).field_int32());
247}
248
Bookatz3e906582018-12-10 17:26:58 -0800249TEST(StatsLogProcessorTest, TestOnDumpReportEraseData) {
250 // Setup a simple config.
251 StatsdConfig config;
252 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
253 auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
254 *config.add_atom_matcher() = wakelockAcquireMatcher;
255
256 auto countMetric = config.add_count_metric();
257 countMetric->set_id(123456);
258 countMetric->set_what(wakelockAcquireMatcher.id());
259 countMetric->set_bucket(FIVE_MINUTES);
260
261 ConfigKey cfgKey;
262 sp<StatsLogProcessor> processor = CreateStatsLogProcessor(1, 1, config, cfgKey);
263
264 std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
265 auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 2);
266 processor->OnLogEvent(event.get());
267
268 vector<uint8_t> bytes;
269 ConfigMetricsReportList output;
270
271 // Dump report WITHOUT erasing data.
Olivier Gaillard6c75ecd2019-02-20 09:57:33 +0000272 processor->onDumpReport(cfgKey, 3, true, false /* Do NOT erase data. */, ADB_DUMP, FAST, &bytes);
Bookatz3e906582018-12-10 17:26:58 -0800273 output.ParseFromArray(bytes.data(), bytes.size());
274 EXPECT_EQ(output.reports_size(), 1);
275 EXPECT_EQ(output.reports(0).metrics_size(), 1);
276 EXPECT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
277
278 // Dump report WITH erasing data. There should be data since we didn't previously erase it.
Olivier Gaillard6c75ecd2019-02-20 09:57:33 +0000279 processor->onDumpReport(cfgKey, 4, true, true /* DO erase data. */, ADB_DUMP, FAST, &bytes);
Bookatz3e906582018-12-10 17:26:58 -0800280 output.ParseFromArray(bytes.data(), bytes.size());
281 EXPECT_EQ(output.reports_size(), 1);
282 EXPECT_EQ(output.reports(0).metrics_size(), 1);
283 EXPECT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
284
285 // Dump report again. There should be no data since we erased it.
Olivier Gaillard6c75ecd2019-02-20 09:57:33 +0000286 processor->onDumpReport(cfgKey, 5, true, true /* DO erase data. */, ADB_DUMP, FAST, &bytes);
Bookatz3e906582018-12-10 17:26:58 -0800287 output.ParseFromArray(bytes.data(), bytes.size());
Bookatzea20bff2018-12-18 10:07:56 -0800288 // We don't care whether statsd has a report, as long as it has no count metrics in it.
289 bool noData = output.reports_size() == 0
290 || output.reports(0).metrics_size() == 0
291 || output.reports(0).metrics(0).count_metrics().data_size() == 0;
Bookatz3e906582018-12-10 17:26:58 -0800292 EXPECT_TRUE(noData);
293}
294
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800295TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) {
296 int uid = 1111;
297
298 // Setup a simple config, no activation
299 StatsdConfig config1;
Tej Singhd823aeb2019-02-13 16:43:49 -0800300 int64_t cfgId1 = 12341;
301 config1.set_id(cfgId1);
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800302 config1.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
303 auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
304 *config1.add_atom_matcher() = wakelockAcquireMatcher;
305
306 long metricId1 = 1234561;
307 long metricId2 = 1234562;
308 auto countMetric1 = config1.add_count_metric();
309 countMetric1->set_id(metricId1);
310 countMetric1->set_what(wakelockAcquireMatcher.id());
311 countMetric1->set_bucket(FIVE_MINUTES);
312
313 auto countMetric2 = config1.add_count_metric();
314 countMetric2->set_id(metricId2);
315 countMetric2->set_what(wakelockAcquireMatcher.id());
316 countMetric2->set_bucket(FIVE_MINUTES);
317
Tej Singhd823aeb2019-02-13 16:43:49 -0800318 ConfigKey cfgKey1(uid, cfgId1);
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800319
320 // Add another config, with two metrics, one with activation
321 StatsdConfig config2;
Tej Singhd823aeb2019-02-13 16:43:49 -0800322 int64_t cfgId2 = 12342;
323 config2.set_id(cfgId2);
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800324 config2.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
325 *config2.add_atom_matcher() = wakelockAcquireMatcher;
326
327 long metricId3 = 1234561;
328 long metricId4 = 1234562;
329
330 auto countMetric3 = config2.add_count_metric();
331 countMetric3->set_id(metricId3);
332 countMetric3->set_what(wakelockAcquireMatcher.id());
333 countMetric3->set_bucket(FIVE_MINUTES);
334
335 auto countMetric4 = config2.add_count_metric();
336 countMetric4->set_id(metricId4);
337 countMetric4->set_what(wakelockAcquireMatcher.id());
338 countMetric4->set_bucket(FIVE_MINUTES);
339
340 auto metric3Activation = config2.add_metric_activation();
341 metric3Activation->set_metric_id(metricId3);
342 auto metric3ActivationTrigger = metric3Activation->add_event_activation();
343 metric3ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
344 metric3ActivationTrigger->set_ttl_seconds(100);
345
Tej Singhd823aeb2019-02-13 16:43:49 -0800346 ConfigKey cfgKey2(uid, cfgId2);
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800347
348 // Add another config, with two metrics, both with activations
349 StatsdConfig config3;
Tej Singhd823aeb2019-02-13 16:43:49 -0800350 int64_t cfgId3 = 12343;
351 config3.set_id(cfgId3);
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800352 config3.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
353 *config3.add_atom_matcher() = wakelockAcquireMatcher;
354
355 long metricId5 = 1234565;
356 long metricId6 = 1234566;
357 auto countMetric5 = config3.add_count_metric();
358 countMetric5->set_id(metricId5);
359 countMetric5->set_what(wakelockAcquireMatcher.id());
360 countMetric5->set_bucket(FIVE_MINUTES);
361
362 auto countMetric6 = config3.add_count_metric();
363 countMetric6->set_id(metricId6);
364 countMetric6->set_what(wakelockAcquireMatcher.id());
365 countMetric6->set_bucket(FIVE_MINUTES);
366
367 auto metric5Activation = config3.add_metric_activation();
368 metric5Activation->set_metric_id(metricId5);
369 auto metric5ActivationTrigger = metric5Activation->add_event_activation();
370 metric5ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
371 metric5ActivationTrigger->set_ttl_seconds(100);
372
373 auto metric6Activation = config3.add_metric_activation();
374 metric6Activation->set_metric_id(metricId6);
375 auto metric6ActivationTrigger = metric6Activation->add_event_activation();
376 metric6ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
377 metric6ActivationTrigger->set_ttl_seconds(200);
378
Tej Singhd823aeb2019-02-13 16:43:49 -0800379 ConfigKey cfgKey3(uid, cfgId3);
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800380
Tej Singhd823aeb2019-02-13 16:43:49 -0800381 sp<UidMap> m = new UidMap();
382 sp<StatsPullerManager> pullerManager = new StatsPullerManager();
383 sp<AlarmMonitor> anomalyAlarmMonitor;
384 sp<AlarmMonitor> subscriberAlarmMonitor;
385 vector<int64_t> activeConfigsBroadcast;
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800386
Tej Singhd823aeb2019-02-13 16:43:49 -0800387 long timeBase1 = 1;
388 int broadcastCount = 0;
389 StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
390 timeBase1, [](const ConfigKey& key) { return true; },
391 [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
392 const vector<int64_t>& activeConfigs) {
393 broadcastCount++;
394 EXPECT_EQ(broadcastUid, uid);
395 activeConfigsBroadcast.clear();
396 activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
397 activeConfigs.begin(), activeConfigs.end());
398 return true;
399 });
400
401 processor.OnConfigUpdated(1, cfgKey1, config1);
402 processor.OnConfigUpdated(2, cfgKey2, config2);
403 processor.OnConfigUpdated(3, cfgKey3, config3);
404
405 EXPECT_EQ(3, processor.mMetricsManagers.size());
406
407 // Expect the first config and both metrics in it to be active.
408 auto it = processor.mMetricsManagers.find(cfgKey1);
409 EXPECT_TRUE(it != processor.mMetricsManagers.end());
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800410 auto& metricsManager1 = it->second;
411 EXPECT_TRUE(metricsManager1->isActive());
412
413 auto metricIt = metricsManager1->mAllMetricProducers.begin();
414 for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
415 if ((*metricIt)->getMetricId() == metricId1) {
416 break;
417 }
418 }
419 EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
420 auto& metricProducer1 = *metricIt;
421 EXPECT_TRUE(metricProducer1->isActive());
422
423 metricIt = metricsManager1->mAllMetricProducers.begin();
424 for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
425 if ((*metricIt)->getMetricId() == metricId2) {
426 break;
427 }
428 }
429 EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
430 auto& metricProducer2 = *metricIt;
431 EXPECT_TRUE(metricProducer2->isActive());
432
Tej Singhd823aeb2019-02-13 16:43:49 -0800433 // Expect config 2 to be active. Metric 3 shouldn't be active, metric 4 should be active.
434 it = processor.mMetricsManagers.find(cfgKey2);
435 EXPECT_TRUE(it != processor.mMetricsManagers.end());
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800436 auto& metricsManager2 = it->second;
437 EXPECT_TRUE(metricsManager2->isActive());
438
439 metricIt = metricsManager2->mAllMetricProducers.begin();
440 for (; metricIt != metricsManager2->mAllMetricProducers.end(); metricIt++) {
441 if ((*metricIt)->getMetricId() == metricId3) {
442 break;
443 }
444 }
445 EXPECT_TRUE(metricIt != metricsManager2->mAllMetricProducers.end());
446 auto& metricProducer3 = *metricIt;
447 EXPECT_FALSE(metricProducer3->isActive());
448
449 metricIt = metricsManager2->mAllMetricProducers.begin();
450 for (; metricIt != metricsManager2->mAllMetricProducers.end(); metricIt++) {
451 if ((*metricIt)->getMetricId() == metricId4) {
452 break;
453 }
454 }
455 EXPECT_TRUE(metricIt != metricsManager2->mAllMetricProducers.end());
456 auto& metricProducer4 = *metricIt;
457 EXPECT_TRUE(metricProducer4->isActive());
458
Tej Singhd823aeb2019-02-13 16:43:49 -0800459 // Expect the third config and both metrics in it to be inactive.
460 it = processor.mMetricsManagers.find(cfgKey3);
461 EXPECT_TRUE(it != processor.mMetricsManagers.end());
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800462 auto& metricsManager3 = it->second;
463 EXPECT_FALSE(metricsManager3->isActive());
464
465 metricIt = metricsManager3->mAllMetricProducers.begin();
466 for (; metricIt != metricsManager2->mAllMetricProducers.end(); metricIt++) {
467 if ((*metricIt)->getMetricId() == metricId5) {
468 break;
469 }
470 }
471 EXPECT_TRUE(metricIt != metricsManager3->mAllMetricProducers.end());
472 auto& metricProducer5 = *metricIt;
473 EXPECT_FALSE(metricProducer5->isActive());
474
475 metricIt = metricsManager3->mAllMetricProducers.begin();
476 for (; metricIt != metricsManager3->mAllMetricProducers.end(); metricIt++) {
477 if ((*metricIt)->getMetricId() == metricId6) {
478 break;
479 }
480 }
481 EXPECT_TRUE(metricIt != metricsManager3->mAllMetricProducers.end());
482 auto& metricProducer6 = *metricIt;
483 EXPECT_FALSE(metricProducer6->isActive());
484
Tej Singhd823aeb2019-02-13 16:43:49 -0800485 // No broadcast for active configs should have happened yet.
486 EXPECT_EQ(broadcastCount, 0);
487
488 // Activate all 3 metrics that were not active.
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800489 std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
490 auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
Tej Singhd823aeb2019-02-13 16:43:49 -0800491 processor.OnLogEvent(event.get());
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800492
Tej Singhd823aeb2019-02-13 16:43:49 -0800493 // Assert that all 3 configs are active.
494 EXPECT_TRUE(metricsManager1->isActive());
495 EXPECT_TRUE(metricsManager2->isActive());
496 EXPECT_TRUE(metricsManager3->isActive());
497
498 // A broadcast should have happened, and all 3 configs should be active in the broadcast.
499 EXPECT_EQ(broadcastCount, 1);
500 EXPECT_EQ(activeConfigsBroadcast.size(), 3);
501 EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId1)
502 != activeConfigsBroadcast.end());
503 EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId2)
504 != activeConfigsBroadcast.end());
505 EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId3)
506 != activeConfigsBroadcast.end());
507
508 // When we shut down, metrics 3 & 5 have 100ns remaining, metric 6 has 100s + 100ns.
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800509 int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
510 EXPECT_TRUE(metricProducer3->isActive());
511 int64_t ttl3 = metricProducer3->getRemainingTtlNs(shutDownTime);
512 EXPECT_EQ(100, ttl3);
513 EXPECT_TRUE(metricProducer5->isActive());
514 int64_t ttl5 = metricProducer5->getRemainingTtlNs(shutDownTime);
515 EXPECT_EQ(100, ttl5);
516 EXPECT_TRUE(metricProducer6->isActive());
517 int64_t ttl6 = metricProducer6->getRemainingTtlNs(shutDownTime);
518 EXPECT_EQ(100 + 100 * NS_PER_SEC, ttl6);
519
Tej Singhd823aeb2019-02-13 16:43:49 -0800520 processor.WriteMetricsActivationToDisk(shutDownTime);
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800521
Tej Singhd823aeb2019-02-13 16:43:49 -0800522 // Create a second StatsLogProcessor and push the same 3 configs.
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800523 long timeBase2 = 1000;
524 sp<StatsLogProcessor> processor2 =
525 CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
526 processor2->OnConfigUpdated(timeBase2, cfgKey2, config2);
527 processor2->OnConfigUpdated(timeBase2, cfgKey3, config3);
528
529 EXPECT_EQ(3, processor2->mMetricsManagers.size());
Tej Singhd823aeb2019-02-13 16:43:49 -0800530
531 // First config and both metrics are active.
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800532 it = processor2->mMetricsManagers.find(cfgKey1);
533 EXPECT_TRUE(it != processor2->mMetricsManagers.end());
534 auto& metricsManager1001 = it->second;
535 EXPECT_TRUE(metricsManager1001->isActive());
536
537 metricIt = metricsManager1001->mAllMetricProducers.begin();
538 for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
539 if ((*metricIt)->getMetricId() == metricId1) {
540 break;
541 }
542 }
543 EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
544 auto& metricProducer1001 = *metricIt;
545 EXPECT_TRUE(metricProducer1001->isActive());
546
547 metricIt = metricsManager1001->mAllMetricProducers.begin();
548 for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
549 if ((*metricIt)->getMetricId() == metricId2) {
550 break;
551 }
552 }
553 EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
554 auto& metricProducer1002 = *metricIt;
555 EXPECT_TRUE(metricProducer1002->isActive());
556
Tej Singhd823aeb2019-02-13 16:43:49 -0800557 // Second config is active. Metric 3 is inactive, metric 4 is active.
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800558 it = processor2->mMetricsManagers.find(cfgKey2);
559 EXPECT_TRUE(it != processor2->mMetricsManagers.end());
560 auto& metricsManager1002 = it->second;
561 EXPECT_TRUE(metricsManager1002->isActive());
562
563 metricIt = metricsManager1002->mAllMetricProducers.begin();
564 for (; metricIt != metricsManager1002->mAllMetricProducers.end(); metricIt++) {
565 if ((*metricIt)->getMetricId() == metricId3) {
566 break;
567 }
568 }
569 EXPECT_TRUE(metricIt != metricsManager1002->mAllMetricProducers.end());
570 auto& metricProducer1003 = *metricIt;
571 EXPECT_FALSE(metricProducer1003->isActive());
572
573 metricIt = metricsManager1002->mAllMetricProducers.begin();
574 for (; metricIt != metricsManager1002->mAllMetricProducers.end(); metricIt++) {
575 if ((*metricIt)->getMetricId() == metricId4) {
576 break;
577 }
578 }
579 EXPECT_TRUE(metricIt != metricsManager1002->mAllMetricProducers.end());
580 auto& metricProducer1004 = *metricIt;
581 EXPECT_TRUE(metricProducer1004->isActive());
582
Tej Singhd823aeb2019-02-13 16:43:49 -0800583 // Config 3 is inactive. both metrics are inactive.
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800584 it = processor2->mMetricsManagers.find(cfgKey3);
585 EXPECT_TRUE(it != processor2->mMetricsManagers.end());
586 auto& metricsManager1003 = it->second;
587 EXPECT_FALSE(metricsManager1003->isActive());
588 EXPECT_EQ(2, metricsManager1003->mAllMetricProducers.size());
589
590 metricIt = metricsManager1003->mAllMetricProducers.begin();
591 for (; metricIt != metricsManager1002->mAllMetricProducers.end(); metricIt++) {
592 if ((*metricIt)->getMetricId() == metricId5) {
593 break;
594 }
595 }
596 EXPECT_TRUE(metricIt != metricsManager1003->mAllMetricProducers.end());
597 auto& metricProducer1005 = *metricIt;
598 EXPECT_FALSE(metricProducer1005->isActive());
599
600 metricIt = metricsManager1003->mAllMetricProducers.begin();
601 for (; metricIt != metricsManager1003->mAllMetricProducers.end(); metricIt++) {
602 if ((*metricIt)->getMetricId() == metricId6) {
603 break;
604 }
605 }
606 EXPECT_TRUE(metricIt != metricsManager1003->mAllMetricProducers.end());
607 auto& metricProducer1006 = *metricIt;
608 EXPECT_FALSE(metricProducer1006->isActive());
609
Tej Singhd823aeb2019-02-13 16:43:49 -0800610 // Assert that all 3 metrics with activation are inactive and that the ttls were properly set.
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800611 EXPECT_FALSE(metricProducer1003->isActive());
612 const auto& activation1003 = metricProducer1003->mEventActivationMap.begin()->second;
613 EXPECT_EQ(100 * NS_PER_SEC, activation1003.ttl_ns);
614 EXPECT_EQ(0, activation1003.activation_ns);
615 EXPECT_FALSE(metricProducer1005->isActive());
616 const auto& activation1005 = metricProducer1005->mEventActivationMap.begin()->second;
617 EXPECT_EQ(100 * NS_PER_SEC, activation1005.ttl_ns);
618 EXPECT_EQ(0, activation1005.activation_ns);
619 EXPECT_FALSE(metricProducer1006->isActive());
620 const auto& activation1006 = metricProducer1006->mEventActivationMap.begin()->second;
621 EXPECT_EQ(200 * NS_PER_SEC, activation1006.ttl_ns);
622 EXPECT_EQ(0, activation1006.activation_ns);
623
624 processor2->LoadMetricsActivationFromDisk();
625
Tej Singhd823aeb2019-02-13 16:43:49 -0800626 // After loading activations from disk, assert that all 3 metrics are active.
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800627 EXPECT_TRUE(metricProducer1003->isActive());
628 EXPECT_EQ(timeBase2 + ttl3 - activation1003.ttl_ns, activation1003.activation_ns);
629 EXPECT_TRUE(metricProducer1005->isActive());
630 EXPECT_EQ(timeBase2 + ttl5 - activation1005.ttl_ns, activation1005.activation_ns);
631 EXPECT_TRUE(metricProducer1006->isActive());
632 EXPECT_EQ(timeBase2 + ttl6 - activation1006.ttl_ns, activation1003.activation_ns);
Tej Singhd823aeb2019-02-13 16:43:49 -0800633
634 // Make sure no more broadcasts have happened.
635 EXPECT_EQ(broadcastCount, 1);
Chenjie Yuc7939cb2019-02-04 17:25:45 -0800636}
637
Chenjie Yua9a310e2019-02-06 13:40:10 -0800638TEST(StatsLogProcessorTest, TestActivationOnBoot) {
639 int uid = 1111;
640
641 // Setup a simple config, no activation
642 StatsdConfig config1;
643 config1.set_id(12341);
644 config1.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
645 auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
646 *config1.add_atom_matcher() = wakelockAcquireMatcher;
647
648 long metricId1 = 1234561;
649 long metricId2 = 1234562;
650 auto countMetric1 = config1.add_count_metric();
651 countMetric1->set_id(metricId1);
652 countMetric1->set_what(wakelockAcquireMatcher.id());
653 countMetric1->set_bucket(FIVE_MINUTES);
654
655 auto countMetric2 = config1.add_count_metric();
656 countMetric2->set_id(metricId2);
657 countMetric2->set_what(wakelockAcquireMatcher.id());
658 countMetric2->set_bucket(FIVE_MINUTES);
659
660 auto metric1Activation = config1.add_metric_activation();
661 metric1Activation->set_metric_id(metricId1);
662 metric1Activation->set_activation_type(MetricActivation::ACTIVATE_ON_BOOT);
663 auto metric1ActivationTrigger = metric1Activation->add_event_activation();
664 metric1ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
665 metric1ActivationTrigger->set_ttl_seconds(100);
666
667 ConfigKey cfgKey1(uid, 12341);
668 long timeBase1 = 1;
669 sp<StatsLogProcessor> processor =
670 CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
671
672 EXPECT_EQ(1, processor->mMetricsManagers.size());
673 auto it = processor->mMetricsManagers.find(cfgKey1);
674 EXPECT_TRUE(it != processor->mMetricsManagers.end());
675 auto& metricsManager1 = it->second;
676 EXPECT_TRUE(metricsManager1->isActive());
677
678 auto metricIt = metricsManager1->mAllMetricProducers.begin();
679 for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
680 if ((*metricIt)->getMetricId() == metricId1) {
681 break;
682 }
683 }
684 EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
685 auto& metricProducer1 = *metricIt;
686 EXPECT_FALSE(metricProducer1->isActive());
687
688 metricIt = metricsManager1->mAllMetricProducers.begin();
689 for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
690 if ((*metricIt)->getMetricId() == metricId2) {
691 break;
692 }
693 }
694 EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
695 auto& metricProducer2 = *metricIt;
696 EXPECT_TRUE(metricProducer2->isActive());
697
698 const auto& activation1 = metricProducer1->mEventActivationMap.begin()->second;
699 EXPECT_EQ(100 * NS_PER_SEC, activation1.ttl_ns);
700 EXPECT_EQ(0, activation1.activation_ns);
701 EXPECT_EQ(kNotActive, activation1.state);
702
703 std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
704 auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
705 processor->OnLogEvent(event.get());
706
707 EXPECT_FALSE(metricProducer1->isActive());
708 EXPECT_EQ(0, activation1.activation_ns);
709 EXPECT_EQ(kActiveOnBoot, activation1.state);
710
711 int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
712
713 processor->WriteMetricsActivationToDisk(shutDownTime);
714 EXPECT_TRUE(metricProducer1->isActive());
715 int64_t ttl1 = metricProducer1->getRemainingTtlNs(shutDownTime);
716 EXPECT_EQ(100 * NS_PER_SEC, ttl1);
717
718 long timeBase2 = 1000;
719 sp<StatsLogProcessor> processor2 =
720 CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
721
722 EXPECT_EQ(1, processor2->mMetricsManagers.size());
723 it = processor2->mMetricsManagers.find(cfgKey1);
724 EXPECT_TRUE(it != processor2->mMetricsManagers.end());
725 auto& metricsManager1001 = it->second;
726 EXPECT_TRUE(metricsManager1001->isActive());
727
728 metricIt = metricsManager1001->mAllMetricProducers.begin();
729 for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
730 if ((*metricIt)->getMetricId() == metricId1) {
731 break;
732 }
733 }
734 EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
735 auto& metricProducer1001 = *metricIt;
736 EXPECT_FALSE(metricProducer1001->isActive());
737
738 metricIt = metricsManager1001->mAllMetricProducers.begin();
739 for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
740 if ((*metricIt)->getMetricId() == metricId2) {
741 break;
742 }
743 }
744 EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
745 auto& metricProducer1002 = *metricIt;
746 EXPECT_TRUE(metricProducer1002->isActive());
747
748 const auto& activation1001 = metricProducer1001->mEventActivationMap.begin()->second;
749 EXPECT_EQ(100 * NS_PER_SEC, activation1001.ttl_ns);
750 EXPECT_EQ(0, activation1001.activation_ns);
751 EXPECT_EQ(kNotActive, activation1001.state);
752
753 processor2->LoadMetricsActivationFromDisk();
754
755 EXPECT_TRUE(metricProducer1001->isActive());
756 EXPECT_EQ(timeBase2 + ttl1 - activation1001.ttl_ns, activation1001.activation_ns);
757}
758
David Chend9269e22017-12-05 13:43:51 -0800759#else
760GTEST_LOG_(INFO) << "This test does nothing.\n";
761#endif
762
763} // namespace statsd
764} // namespace os
Yao Chen288c6002017-12-12 13:43:18 -0800765} // namespace android