1 // 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 #pragma once
16 
17 #include <aidl/android/os/BnPullAtomCallback.h>
18 #include <aidl/android/os/IPullAtomCallback.h>
19 #include <aidl/android/os/IPullAtomResultReceiver.h>
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 
23 #include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
24 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
25 #include "src/StatsLogProcessor.h"
26 #include "src/hash.h"
27 #include "src/logd/LogEvent.h"
28 #include "src/packages/UidMap.h"
29 #include "src/stats_log_util.h"
30 #include "stats_event.h"
31 #include "statslog_statsdtest.h"
32 
33 namespace android {
34 namespace os {
35 namespace statsd {
36 
37 using namespace testing;
38 using ::aidl::android::os::BnPullAtomCallback;
39 using ::aidl::android::os::IPullAtomCallback;
40 using ::aidl::android::os::IPullAtomResultReceiver;
41 using android::util::ProtoReader;
42 using google::protobuf::RepeatedPtrField;
43 using Status = ::ndk::ScopedAStatus;
44 
45 const int SCREEN_STATE_ATOM_ID = util::SCREEN_STATE_CHANGED;
46 const int UID_PROCESS_STATE_ATOM_ID = util::UID_PROCESS_STATE_CHANGED;
47 
48 enum BucketSplitEvent { APP_UPGRADE, BOOT_COMPLETE };
49 
50 class MockUidMap : public UidMap {
51 public:
52     MOCK_METHOD(int, getHostUidOrSelf, (int uid), (const));
53     MOCK_METHOD(std::set<int32_t>, getAppUid, (const string& package), (const));
54 };
55 
56 // Converts a ProtoOutputStream to a StatsLogReport proto.
57 StatsLogReport outputStreamToProto(ProtoOutputStream* proto);
58 
59 // Create AtomMatcher proto to simply match a specific atom type.
60 AtomMatcher CreateSimpleAtomMatcher(const string& name, int atomId);
61 
62 // Create AtomMatcher proto for temperature atom.
63 AtomMatcher CreateTemperatureAtomMatcher();
64 
65 // Create AtomMatcher proto for scheduled job state changed.
66 AtomMatcher CreateScheduledJobStateChangedAtomMatcher();
67 
68 // Create AtomMatcher proto for starting a scheduled job.
69 AtomMatcher CreateStartScheduledJobAtomMatcher();
70 
71 // Create AtomMatcher proto for a scheduled job is done.
72 AtomMatcher CreateFinishScheduledJobAtomMatcher();
73 
74 // Create AtomMatcher proto for screen brightness state changed.
75 AtomMatcher CreateScreenBrightnessChangedAtomMatcher();
76 
77 // Create AtomMatcher proto for starting battery save mode.
78 AtomMatcher CreateBatterySaverModeStartAtomMatcher();
79 
80 // Create AtomMatcher proto for stopping battery save mode.
81 AtomMatcher CreateBatterySaverModeStopAtomMatcher();
82 
83 // Create AtomMatcher proto for battery state none mode.
84 AtomMatcher CreateBatteryStateNoneMatcher();
85 
86 // Create AtomMatcher proto for battery state usb mode.
87 AtomMatcher CreateBatteryStateUsbMatcher();
88 
89 // Create AtomMatcher proto for process state changed.
90 AtomMatcher CreateUidProcessStateChangedAtomMatcher();
91 
92 // Create AtomMatcher proto for acquiring wakelock.
93 AtomMatcher CreateAcquireWakelockAtomMatcher();
94 
95 // Create AtomMatcher proto for releasing wakelock.
96 AtomMatcher CreateReleaseWakelockAtomMatcher() ;
97 
98 // Create AtomMatcher proto for screen turned on.
99 AtomMatcher CreateScreenTurnedOnAtomMatcher();
100 
101 // Create AtomMatcher proto for screen turned off.
102 AtomMatcher CreateScreenTurnedOffAtomMatcher();
103 
104 // Create AtomMatcher proto for app sync turned on.
105 AtomMatcher CreateSyncStartAtomMatcher();
106 
107 // Create AtomMatcher proto for app sync turned off.
108 AtomMatcher CreateSyncEndAtomMatcher();
109 
110 // Create AtomMatcher proto for app sync moves to background.
111 AtomMatcher CreateMoveToBackgroundAtomMatcher();
112 
113 // Create AtomMatcher proto for app sync moves to foreground.
114 AtomMatcher CreateMoveToForegroundAtomMatcher();
115 
116 // Create AtomMatcher proto for process crashes
117 AtomMatcher CreateProcessCrashAtomMatcher() ;
118 
119 // Create Predicate proto for screen is on.
120 Predicate CreateScreenIsOnPredicate();
121 
122 // Create Predicate proto for screen is off.
123 Predicate CreateScreenIsOffPredicate();
124 
125 // Create Predicate proto for a running scheduled job.
126 Predicate CreateScheduledJobPredicate();
127 
128 // Create Predicate proto for battery saver mode.
129 Predicate CreateBatterySaverModePredicate();
130 
131 // Create Predicate proto for device unplogged mode.
132 Predicate CreateDeviceUnpluggedPredicate();
133 
134 // Create Predicate proto for holding wakelock.
135 Predicate CreateHoldingWakelockPredicate();
136 
137 // Create a Predicate proto for app syncing.
138 Predicate CreateIsSyncingPredicate();
139 
140 // Create a Predicate proto for app is in background.
141 Predicate CreateIsInBackgroundPredicate();
142 
143 // Create State proto for screen state atom.
144 State CreateScreenState();
145 
146 // Create State proto for uid process state atom.
147 State CreateUidProcessState();
148 
149 // Create State proto for overlay state atom.
150 State CreateOverlayState();
151 
152 // Create State proto for screen state atom with on/off map.
153 State CreateScreenStateWithOnOffMap(int64_t screenOnId, int64_t screenOffId);
154 
155 // Create State proto for screen state atom with simple on/off map.
156 State CreateScreenStateWithSimpleOnOffMap(int64_t screenOnId, int64_t screenOffId);
157 
158 // Create StateGroup proto for ScreenState ON group
159 StateMap_StateGroup CreateScreenStateOnGroup(int64_t screenOnId);
160 
161 // Create StateGroup proto for ScreenState OFF group
162 StateMap_StateGroup CreateScreenStateOffGroup(int64_t screenOffId);
163 
164 // Create StateGroup proto for simple ScreenState ON group
165 StateMap_StateGroup CreateScreenStateSimpleOnGroup(int64_t screenOnId);
166 
167 // Create StateGroup proto for simple ScreenState OFF group
168 StateMap_StateGroup CreateScreenStateSimpleOffGroup(int64_t screenOffId);
169 
170 // Create StateMap proto for ScreenState ON/OFF map
171 StateMap CreateScreenStateOnOffMap(int64_t screenOnId, int64_t screenOffId);
172 
173 // Create StateMap proto for simple ScreenState ON/OFF map
174 StateMap CreateScreenStateSimpleOnOffMap(int64_t screenOnId, int64_t screenOffId);
175 
176 // Add a predicate to the predicate combination.
177 void addPredicateToPredicateCombination(const Predicate& predicate, Predicate* combination);
178 
179 // Create dimensions from primitive fields.
180 FieldMatcher CreateDimensions(const int atomId, const std::vector<int>& fields);
181 
182 // Create dimensions by attribution uid and tag.
183 FieldMatcher CreateAttributionUidAndTagDimensions(const int atomId,
184                                                   const std::vector<Position>& positions);
185 
186 // Create dimensions by attribution uid only.
187 FieldMatcher CreateAttributionUidDimensions(const int atomId,
188                                             const std::vector<Position>& positions);
189 
190 FieldMatcher CreateAttributionUidAndOtherDimensions(const int atomId,
191                                                     const std::vector<Position>& positions,
192                                                     const std::vector<int>& fields);
193 
194 // START: get primary key functions
195 // These functions take in atom field information and create FieldValues which are stored in the
196 // given HashableDimensionKey.
197 void getUidProcessKey(int uid, HashableDimensionKey* key);
198 
199 void getOverlayKey(int uid, string packageName, HashableDimensionKey* key);
200 
201 void getPartialWakelockKey(int uid, const std::string& tag, HashableDimensionKey* key);
202 
203 void getPartialWakelockKey(int uid, HashableDimensionKey* key);
204 // END: get primary key functions
205 
206 void writeAttribution(AStatsEvent* statsEvent, const vector<int>& attributionUids,
207                       const vector<string>& attributionTags);
208 
209 // Builds statsEvent to get buffer that is parsed into logEvent then releases statsEvent.
210 void parseStatsEventToLogEvent(AStatsEvent* statsEvent, LogEvent* logEvent);
211 
212 shared_ptr<LogEvent> CreateTwoValueLogEvent(int atomId, int64_t eventTimeNs, int32_t value1,
213                                             int32_t value2);
214 
215 void CreateTwoValueLogEvent(LogEvent* logEvent, int atomId, int64_t eventTimeNs, int32_t value1,
216                             int32_t value2);
217 
218 shared_ptr<LogEvent> CreateThreeValueLogEvent(int atomId, int64_t eventTimeNs, int32_t value1,
219                                               int32_t value2, int32_t value3);
220 
221 void CreateThreeValueLogEvent(LogEvent* logEvent, int atomId, int64_t eventTimeNs, int32_t value1,
222                               int32_t value2, int32_t value3);
223 
224 // The repeated value log event helpers create a log event with two int fields, both
225 // set to the same value. This is useful for testing metrics that are only interested
226 // in the value of the second field but still need the first field to be populated.
227 std::shared_ptr<LogEvent> CreateRepeatedValueLogEvent(int atomId, int64_t eventTimeNs,
228                                                       int32_t value);
229 
230 void CreateRepeatedValueLogEvent(LogEvent* logEvent, int atomId, int64_t eventTimeNs,
231                                  int32_t value);
232 
233 std::shared_ptr<LogEvent> CreateNoValuesLogEvent(int atomId, int64_t eventTimeNs);
234 
235 void CreateNoValuesLogEvent(LogEvent* logEvent, int atomId, int64_t eventTimeNs);
236 
237 std::shared_ptr<LogEvent> makeUidLogEvent(int atomId, int64_t eventTimeNs, int uid, int data1,
238                                           int data2);
239 
240 std::shared_ptr<LogEvent> makeAttributionLogEvent(int atomId, int64_t eventTimeNs,
241                                                   const vector<int>& uids,
242                                                   const vector<string>& tags, int data1, int data2);
243 
244 sp<MockUidMap> makeMockUidMapForOneHost(int hostUid, const vector<int>& isolatedUids);
245 
246 sp<MockUidMap> makeMockUidMapForPackage(const string& pkg, const set<int32_t>& uids);
247 
248 // Create log event for screen state changed.
249 std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(uint64_t timestampNs,
250                                                         const android::view::DisplayStateEnum state,
251                                                         int loggerUid = 0);
252 
253 // Create log event for screen brightness state changed.
254 std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(uint64_t timestampNs, int level);
255 
256 // Create log event when scheduled job starts.
257 std::unique_ptr<LogEvent> CreateStartScheduledJobEvent(uint64_t timestampNs,
258                                                        const vector<int>& attributionUids,
259                                                        const vector<string>& attributionTags,
260                                                        const string& jobName);
261 
262 // Create log event when scheduled job finishes.
263 std::unique_ptr<LogEvent> CreateFinishScheduledJobEvent(uint64_t timestampNs,
264                                                         const vector<int>& attributionUids,
265                                                         const vector<string>& attributionTags,
266                                                         const string& jobName);
267 
268 // Create log event when battery saver starts.
269 std::unique_ptr<LogEvent> CreateBatterySaverOnEvent(uint64_t timestampNs);
270 // Create log event when battery saver stops.
271 std::unique_ptr<LogEvent> CreateBatterySaverOffEvent(uint64_t timestampNs);
272 
273 // Create log event when battery state changes.
274 std::unique_ptr<LogEvent> CreateBatteryStateChangedEvent(const uint64_t timestampNs, const BatteryPluggedStateEnum state);
275 
276 // Create log event for app moving to background.
277 std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(uint64_t timestampNs, const int uid);
278 
279 // Create log event for app moving to foreground.
280 std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(uint64_t timestampNs, const int uid);
281 
282 // Create log event when the app sync starts.
283 std::unique_ptr<LogEvent> CreateSyncStartEvent(uint64_t timestampNs, const vector<int>& uids,
284                                                const vector<string>& tags, const string& name);
285 
286 // Create log event when the app sync ends.
287 std::unique_ptr<LogEvent> CreateSyncEndEvent(uint64_t timestampNs, const vector<int>& uids,
288                                              const vector<string>& tags, const string& name);
289 
290 // Create log event when the app sync ends.
291 std::unique_ptr<LogEvent> CreateAppCrashEvent(uint64_t timestampNs, const int uid);
292 
293 // Create log event for an app crash.
294 std::unique_ptr<LogEvent> CreateAppCrashOccurredEvent(uint64_t timestampNs, const int uid);
295 
296 // Create log event for acquiring wakelock.
297 std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(uint64_t timestampNs, const vector<int>& uids,
298                                                      const vector<string>& tags,
299                                                      const string& wakelockName);
300 
301 // Create log event for releasing wakelock.
302 std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(uint64_t timestampNs, const vector<int>& uids,
303                                                      const vector<string>& tags,
304                                                      const string& wakelockName);
305 
306 // Create log event for releasing wakelock.
307 std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(uint64_t timestampNs, int hostUid,
308                                                         int isolatedUid, bool is_create);
309 
310 // Create log event for uid process state change.
311 std::unique_ptr<LogEvent> CreateUidProcessStateChangedEvent(
312         uint64_t timestampNs, int uid, const android::app::ProcessStateEnum state);
313 
314 std::unique_ptr<LogEvent> CreateBleScanStateChangedEvent(uint64_t timestampNs,
315                                                          const vector<int>& attributionUids,
316                                                          const vector<string>& attributionTags,
317                                                          const BleScanStateChanged::State state,
318                                                          const bool filtered, const bool firstMatch,
319                                                          const bool opportunistic);
320 
321 std::unique_ptr<LogEvent> CreateOverlayStateChangedEvent(int64_t timestampNs, const int32_t uid,
322                                                          const string& packageName,
323                                                          const bool usingAlertWindow,
324                                                          const OverlayStateChanged::State state);
325 
326 // Create a statsd log event processor upon the start time in seconds, config and key.
327 sp<StatsLogProcessor> CreateStatsLogProcessor(const int64_t timeBaseNs, const int64_t currentTimeNs,
328                                               const StatsdConfig& config, const ConfigKey& key,
329                                               const shared_ptr<IPullAtomCallback>& puller = nullptr,
330                                               const int32_t atomTag = 0 /*for puller only*/,
331                                               const sp<UidMap> = new UidMap());
332 
333 // Util function to sort the log events by timestamp.
334 void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events);
335 
336 int64_t StringToId(const string& str);
337 
338 void ValidateWakelockAttributionUidAndTagDimension(const DimensionsValue& value, const int atomId,
339                                                    const int uid, const string& tag);
340 void ValidateUidDimension(const DimensionsValue& value, int node_idx, int atomId, int uid);
341 void ValidateAttributionUidDimension(const DimensionsValue& value, int atomId, int uid);
342 void ValidateAttributionUidAndTagDimension(
343     const DimensionsValue& value, int atomId, int uid, const std::string& tag);
344 void ValidateAttributionUidAndTagDimension(
345     const DimensionsValue& value, int node_idx, int atomId, int uid, const std::string& tag);
346 
347 struct DimensionsPair {
DimensionsPairDimensionsPair348     DimensionsPair(DimensionsValue m1, google::protobuf::RepeatedPtrField<StateValue> m2)
349         : dimInWhat(m1), stateValues(m2){};
350 
351     DimensionsValue dimInWhat;
352     google::protobuf::RepeatedPtrField<StateValue> stateValues;
353 };
354 
355 bool LessThan(const StateValue& s1, const StateValue& s2);
356 bool LessThan(const DimensionsValue& s1, const DimensionsValue& s2);
357 bool LessThan(const DimensionsPair& s1, const DimensionsPair& s2);
358 
359 
360 void backfillStartEndTimestamp(ConfigMetricsReport *config_report);
361 void backfillStartEndTimestamp(ConfigMetricsReportList *config_report_list);
362 
363 void backfillStringInReport(ConfigMetricsReportList *config_report_list);
364 void backfillStringInDimension(const std::map<uint64_t, string>& str_map,
365                                DimensionsValue* dimension);
366 
367 template <typename T>
backfillStringInDimension(const std::map<uint64_t,string> & str_map,T * metrics)368 void backfillStringInDimension(const std::map<uint64_t, string>& str_map,
369                                T* metrics) {
370     for (int i = 0; i < metrics->data_size(); ++i) {
371         auto data = metrics->mutable_data(i);
372         if (data->has_dimensions_in_what()) {
373             backfillStringInDimension(str_map, data->mutable_dimensions_in_what());
374         }
375         if (data->has_dimensions_in_condition()) {
376             backfillStringInDimension(str_map, data->mutable_dimensions_in_condition());
377         }
378     }
379 }
380 
381 void backfillDimensionPath(ConfigMetricsReportList* config_report_list);
382 
383 bool backfillDimensionPath(const DimensionsValue& path,
384                            const google::protobuf::RepeatedPtrField<DimensionsValue>& leafValues,
385                            DimensionsValue* dimension);
386 
387 class FakeSubsystemSleepCallback : public BnPullAtomCallback {
388 public:
389     Status onPullAtom(int atomTag,
390                       const shared_ptr<IPullAtomResultReceiver>& resultReceiver) override;
391 };
392 
393 template <typename T>
backfillDimensionPath(const DimensionsValue & whatPath,const DimensionsValue & conditionPath,T * metricData)394 void backfillDimensionPath(const DimensionsValue& whatPath,
395                            const DimensionsValue& conditionPath,
396                            T* metricData) {
397     for (int i = 0; i < metricData->data_size(); ++i) {
398         auto data = metricData->mutable_data(i);
399         if (data->dimension_leaf_values_in_what_size() > 0) {
400             backfillDimensionPath(whatPath, data->dimension_leaf_values_in_what(),
401                                   data->mutable_dimensions_in_what());
402             data->clear_dimension_leaf_values_in_what();
403         }
404         if (data->dimension_leaf_values_in_condition_size() > 0) {
405             backfillDimensionPath(conditionPath, data->dimension_leaf_values_in_condition(),
406                                   data->mutable_dimensions_in_condition());
407             data->clear_dimension_leaf_values_in_condition();
408         }
409     }
410 }
411 
412 struct DimensionCompare {
operatorDimensionCompare413     bool operator()(const DimensionsPair& s1, const DimensionsPair& s2) const {
414         return LessThan(s1, s2);
415     }
416 };
417 
418 template <typename T>
sortMetricDataByDimensionsValue(const T & metricData,T * sortedMetricData)419 void sortMetricDataByDimensionsValue(const T& metricData, T* sortedMetricData) {
420     std::map<DimensionsPair, int, DimensionCompare> dimensionIndexMap;
421     for (int i = 0; i < metricData.data_size(); ++i) {
422         dimensionIndexMap.insert(
423                 std::make_pair(DimensionsPair(metricData.data(i).dimensions_in_what(),
424                                               metricData.data(i).slice_by_state()),
425                                i));
426     }
427     for (const auto& itr : dimensionIndexMap) {
428         *sortedMetricData->add_data() = metricData.data(itr.second);
429     }
430 }
431 
432 template <typename T>
backfillStartEndTimestampForFullBucket(const int64_t timeBaseNs,const int64_t bucketSizeNs,T * bucket)433 void backfillStartEndTimestampForFullBucket(
434     const int64_t timeBaseNs, const int64_t bucketSizeNs, T* bucket) {
435     bucket->set_start_bucket_elapsed_nanos(timeBaseNs + bucketSizeNs * bucket->bucket_num());
436     bucket->set_end_bucket_elapsed_nanos(
437         timeBaseNs + bucketSizeNs * bucket->bucket_num() + bucketSizeNs);
438     bucket->clear_bucket_num();
439 }
440 
441 template <typename T>
backfillStartEndTimestampForPartialBucket(const int64_t timeBaseNs,T * bucket)442 void backfillStartEndTimestampForPartialBucket(const int64_t timeBaseNs, T* bucket) {
443     if (bucket->has_start_bucket_elapsed_millis()) {
444         bucket->set_start_bucket_elapsed_nanos(
445             MillisToNano(bucket->start_bucket_elapsed_millis()));
446         bucket->clear_start_bucket_elapsed_millis();
447     }
448     if (bucket->has_end_bucket_elapsed_millis()) {
449         bucket->set_end_bucket_elapsed_nanos(
450             MillisToNano(bucket->end_bucket_elapsed_millis()));
451         bucket->clear_end_bucket_elapsed_millis();
452     }
453 }
454 
455 template <typename T>
backfillStartEndTimestampForMetrics(const int64_t timeBaseNs,const int64_t bucketSizeNs,T * metrics)456 void backfillStartEndTimestampForMetrics(const int64_t timeBaseNs, const int64_t bucketSizeNs,
457                                          T* metrics) {
458     for (int i = 0; i < metrics->data_size(); ++i) {
459         auto data = metrics->mutable_data(i);
460         for (int j = 0; j < data->bucket_info_size(); ++j) {
461             auto bucket = data->mutable_bucket_info(j);
462             if (bucket->has_bucket_num()) {
463                 backfillStartEndTimestampForFullBucket(timeBaseNs, bucketSizeNs, bucket);
464             } else {
465                 backfillStartEndTimestampForPartialBucket(timeBaseNs, bucket);
466             }
467         }
468     }
469 }
470 
471 template <typename T>
backfillStartEndTimestampForSkippedBuckets(const int64_t timeBaseNs,T * metrics)472 void backfillStartEndTimestampForSkippedBuckets(const int64_t timeBaseNs, T* metrics) {
473     for (int i = 0; i < metrics->skipped_size(); ++i) {
474         backfillStartEndTimestampForPartialBucket(timeBaseNs, metrics->mutable_skipped(i));
475     }
476 }
477 }  // namespace statsd
478 }  // namespace os
479 }  // namespace android
480