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 <gtest/gtest.h>
18 #include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
19 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
20 #include "src/StatsLogProcessor.h"
21 #include "src/logd/LogEvent.h"
22 #include "src/hash.h"
23 #include "src/stats_log_util.h"
24 #include "statslog.h"
25 
26 namespace android {
27 namespace os {
28 namespace statsd {
29 
30 using google::protobuf::RepeatedPtrField;
31 
32 // Create AtomMatcher proto to simply match a specific atom type.
33 AtomMatcher CreateSimpleAtomMatcher(const string& name, int atomId);
34 
35 // Create AtomMatcher proto for temperature atom.
36 AtomMatcher CreateTemperatureAtomMatcher();
37 
38 // Create AtomMatcher proto for scheduled job state changed.
39 AtomMatcher CreateScheduledJobStateChangedAtomMatcher();
40 
41 // Create AtomMatcher proto for starting a scheduled job.
42 AtomMatcher CreateStartScheduledJobAtomMatcher();
43 
44 // Create AtomMatcher proto for a scheduled job is done.
45 AtomMatcher CreateFinishScheduledJobAtomMatcher();
46 
47 // Create AtomMatcher proto for screen brightness state changed.
48 AtomMatcher CreateScreenBrightnessChangedAtomMatcher();
49 
50 // Create AtomMatcher proto for starting battery save mode.
51 AtomMatcher CreateBatterySaverModeStartAtomMatcher();
52 
53 // Create AtomMatcher proto for stopping battery save mode.
54 AtomMatcher CreateBatterySaverModeStopAtomMatcher();
55 
56 // Create AtomMatcher proto for process state changed.
57 AtomMatcher CreateUidProcessStateChangedAtomMatcher();
58 
59 // Create AtomMatcher proto for acquiring wakelock.
60 AtomMatcher CreateAcquireWakelockAtomMatcher();
61 
62 // Create AtomMatcher proto for releasing wakelock.
63 AtomMatcher CreateReleaseWakelockAtomMatcher() ;
64 
65 // Create AtomMatcher proto for screen turned on.
66 AtomMatcher CreateScreenTurnedOnAtomMatcher();
67 
68 // Create AtomMatcher proto for screen turned off.
69 AtomMatcher CreateScreenTurnedOffAtomMatcher();
70 
71 // Create AtomMatcher proto for app sync turned on.
72 AtomMatcher CreateSyncStartAtomMatcher();
73 
74 // Create AtomMatcher proto for app sync turned off.
75 AtomMatcher CreateSyncEndAtomMatcher();
76 
77 // Create AtomMatcher proto for app sync moves to background.
78 AtomMatcher CreateMoveToBackgroundAtomMatcher();
79 
80 // Create AtomMatcher proto for app sync moves to foreground.
81 AtomMatcher CreateMoveToForegroundAtomMatcher();
82 
83 // Create AtomMatcher proto for process crashes
84 AtomMatcher CreateProcessCrashAtomMatcher() ;
85 
86 // Create Predicate proto for screen is on.
87 Predicate CreateScreenIsOnPredicate();
88 
89 // Create Predicate proto for screen is off.
90 Predicate CreateScreenIsOffPredicate();
91 
92 // Create Predicate proto for a running scheduled job.
93 Predicate CreateScheduledJobPredicate();
94 
95 // Create Predicate proto for battery saver mode.
96 Predicate CreateBatterySaverModePredicate();
97 
98 // Create Predicate proto for holding wakelock.
99 Predicate CreateHoldingWakelockPredicate();
100 
101 // Create a Predicate proto for app syncing.
102 Predicate CreateIsSyncingPredicate();
103 
104 // Create a Predicate proto for app is in background.
105 Predicate CreateIsInBackgroundPredicate();
106 
107 // Add a predicate to the predicate combination.
108 void addPredicateToPredicateCombination(const Predicate& predicate, Predicate* combination);
109 
110 // Create dimensions from primitive fields.
111 FieldMatcher CreateDimensions(const int atomId, const std::vector<int>& fields);
112 
113 // Create dimensions by attribution uid and tag.
114 FieldMatcher CreateAttributionUidAndTagDimensions(const int atomId,
115                                                   const std::vector<Position>& positions);
116 
117 // Create dimensions by attribution uid only.
118 FieldMatcher CreateAttributionUidDimensions(const int atomId,
119                                             const std::vector<Position>& positions);
120 
121 // Create log event for screen state changed.
122 std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
123     const android::view::DisplayStateEnum state, uint64_t timestampNs);
124 
125 // Create log event for screen brightness state changed.
126 std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(
127    int level, uint64_t timestampNs);
128 
129 // Create log event when scheduled job starts.
130 std::unique_ptr<LogEvent> CreateStartScheduledJobEvent(
131     const std::vector<AttributionNodeInternal>& attributions,
132     const string& name, uint64_t timestampNs);
133 
134 // Create log event when scheduled job finishes.
135 std::unique_ptr<LogEvent> CreateFinishScheduledJobEvent(
136     const std::vector<AttributionNodeInternal>& attributions,
137     const string& name, uint64_t timestampNs);
138 
139 // Create log event when battery saver starts.
140 std::unique_ptr<LogEvent> CreateBatterySaverOnEvent(uint64_t timestampNs);
141 // Create log event when battery saver stops.
142 std::unique_ptr<LogEvent> CreateBatterySaverOffEvent(uint64_t timestampNs);
143 
144 // Create log event for app moving to background.
145 std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(const int uid, uint64_t timestampNs);
146 
147 // Create log event for app moving to foreground.
148 std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(const int uid, uint64_t timestampNs);
149 
150 // Create log event when the app sync starts.
151 std::unique_ptr<LogEvent> CreateSyncStartEvent(
152         const std::vector<AttributionNodeInternal>& attributions, const string& name,
153         uint64_t timestampNs);
154 
155 // Create log event when the app sync ends.
156 std::unique_ptr<LogEvent> CreateSyncEndEvent(
157         const std::vector<AttributionNodeInternal>& attributions, const string& name,
158         uint64_t timestampNs);
159 
160 // Create log event when the app sync ends.
161 std::unique_ptr<LogEvent> CreateAppCrashEvent(
162     const int uid, uint64_t timestampNs);
163 
164 // Create log event for acquiring wakelock.
165 std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(
166         const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
167         uint64_t timestampNs);
168 
169 // Create log event for releasing wakelock.
170 std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(
171         const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
172         uint64_t timestampNs);
173 
174 // Create log event for releasing wakelock.
175 std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(
176     int isolatedUid, int hostUid, bool is_create, uint64_t timestampNs);
177 
178 // Helper function to create an AttributionNodeInternal proto.
179 AttributionNodeInternal CreateAttribution(const int& uid, const string& tag);
180 
181 // Create a statsd log event processor upon the start time in seconds, config and key.
182 sp<StatsLogProcessor> CreateStatsLogProcessor(const int64_t timeBaseNs,
183                                               const int64_t currentTimeNs,
184                                               const StatsdConfig& config, const ConfigKey& key);
185 
186 // Util function to sort the log events by timestamp.
187 void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events);
188 
189 int64_t StringToId(const string& str);
190 
191 void ValidateUidDimension(const DimensionsValue& value, int node_idx, int atomId, int uid);
192 void ValidateAttributionUidDimension(const DimensionsValue& value, int atomId, int uid);
193 void ValidateAttributionUidAndTagDimension(
194     const DimensionsValue& value, int atomId, int uid, const std::string& tag);
195 void ValidateAttributionUidAndTagDimension(
196     const DimensionsValue& value, int node_idx, int atomId, int uid, const std::string& tag);
197 
198 struct DimensionsPair {
DimensionsPairDimensionsPair199     DimensionsPair(DimensionsValue m1, DimensionsValue m2) : dimInWhat(m1), dimInCondition(m2){};
200 
201     DimensionsValue dimInWhat;
202     DimensionsValue dimInCondition;
203 };
204 
205 bool LessThan(const DimensionsValue& s1, const DimensionsValue& s2);
206 bool LessThan(const DimensionsPair& s1, const DimensionsPair& s2);
207 
208 
209 void backfillStartEndTimestamp(ConfigMetricsReport *config_report);
210 void backfillStartEndTimestamp(ConfigMetricsReportList *config_report_list);
211 
212 void backfillStringInReport(ConfigMetricsReportList *config_report_list);
213 void backfillStringInDimension(const std::map<uint64_t, string>& str_map,
214                                DimensionsValue* dimension);
215 
216 template <typename T>
backfillStringInDimension(const std::map<uint64_t,string> & str_map,T * metrics)217 void backfillStringInDimension(const std::map<uint64_t, string>& str_map,
218                                T* metrics) {
219     for (int i = 0; i < metrics->data_size(); ++i) {
220         auto data = metrics->mutable_data(i);
221         if (data->has_dimensions_in_what()) {
222             backfillStringInDimension(str_map, data->mutable_dimensions_in_what());
223         }
224         if (data->has_dimensions_in_condition()) {
225             backfillStringInDimension(str_map, data->mutable_dimensions_in_condition());
226         }
227     }
228 }
229 
230 void backfillDimensionPath(ConfigMetricsReportList* config_report_list);
231 
232 bool backfillDimensionPath(const DimensionsValue& path,
233                            const google::protobuf::RepeatedPtrField<DimensionsValue>& leafValues,
234                            DimensionsValue* dimension);
235 
236 template <typename T>
backfillDimensionPath(const DimensionsValue & whatPath,const DimensionsValue & conditionPath,T * metricData)237 void backfillDimensionPath(const DimensionsValue& whatPath,
238                            const DimensionsValue& conditionPath,
239                            T* metricData) {
240     for (int i = 0; i < metricData->data_size(); ++i) {
241         auto data = metricData->mutable_data(i);
242         if (data->dimension_leaf_values_in_what_size() > 0) {
243             backfillDimensionPath(whatPath, data->dimension_leaf_values_in_what(),
244                                   data->mutable_dimensions_in_what());
245             data->clear_dimension_leaf_values_in_what();
246         }
247         if (data->dimension_leaf_values_in_condition_size() > 0) {
248             backfillDimensionPath(conditionPath, data->dimension_leaf_values_in_condition(),
249                                   data->mutable_dimensions_in_condition());
250             data->clear_dimension_leaf_values_in_condition();
251         }
252     }
253 }
254 
255 struct DimensionCompare {
operatorDimensionCompare256     bool operator()(const DimensionsPair& s1, const DimensionsPair& s2) const {
257         return LessThan(s1, s2);
258     }
259 };
260 
261 template <typename T>
sortMetricDataByDimensionsValue(const T & metricData,T * sortedMetricData)262 void sortMetricDataByDimensionsValue(const T& metricData, T* sortedMetricData) {
263     std::map<DimensionsPair, int, DimensionCompare> dimensionIndexMap;
264     for (int i = 0; i < metricData.data_size(); ++i) {
265         dimensionIndexMap.insert(
266                 std::make_pair(DimensionsPair(metricData.data(i).dimensions_in_what(),
267                                               metricData.data(i).dimensions_in_condition()),
268                                i));
269     }
270     for (const auto& itr : dimensionIndexMap) {
271         *sortedMetricData->add_data() = metricData.data(itr.second);
272     }
273 }
274 
275 template <typename T>
backfillStartEndTimestampForFullBucket(const int64_t timeBaseNs,const int64_t bucketSizeNs,T * bucket)276 void backfillStartEndTimestampForFullBucket(
277     const int64_t timeBaseNs, const int64_t bucketSizeNs, T* bucket) {
278     bucket->set_start_bucket_elapsed_nanos(timeBaseNs + bucketSizeNs * bucket->bucket_num());
279     bucket->set_end_bucket_elapsed_nanos(
280         timeBaseNs + bucketSizeNs * bucket->bucket_num() + bucketSizeNs);
281     bucket->clear_bucket_num();
282 }
283 
284 template <typename T>
backfillStartEndTimestampForPartialBucket(const int64_t timeBaseNs,T * bucket)285 void backfillStartEndTimestampForPartialBucket(const int64_t timeBaseNs, T* bucket) {
286     if (bucket->has_start_bucket_elapsed_millis()) {
287         bucket->set_start_bucket_elapsed_nanos(
288             MillisToNano(bucket->start_bucket_elapsed_millis()));
289         bucket->clear_start_bucket_elapsed_millis();
290     }
291     if (bucket->has_end_bucket_elapsed_millis()) {
292         bucket->set_end_bucket_elapsed_nanos(
293             MillisToNano(bucket->end_bucket_elapsed_millis()));
294         bucket->clear_end_bucket_elapsed_millis();
295     }
296 }
297 
298 template <typename T>
backfillStartEndTimestampForMetrics(const int64_t timeBaseNs,const int64_t bucketSizeNs,T * metrics)299 void backfillStartEndTimestampForMetrics(const int64_t timeBaseNs, const int64_t bucketSizeNs,
300                                          T* metrics) {
301     for (int i = 0; i < metrics->data_size(); ++i) {
302         auto data = metrics->mutable_data(i);
303         for (int j = 0; j < data->bucket_info_size(); ++j) {
304             auto bucket = data->mutable_bucket_info(j);
305             if (bucket->has_bucket_num()) {
306                 backfillStartEndTimestampForFullBucket(timeBaseNs, bucketSizeNs, bucket);
307             } else {
308                 backfillStartEndTimestampForPartialBucket(timeBaseNs, bucket);
309             }
310         }
311     }
312 }
313 
314 template <typename T>
backfillStartEndTimestampForSkippedBuckets(const int64_t timeBaseNs,T * metrics)315 void backfillStartEndTimestampForSkippedBuckets(const int64_t timeBaseNs, T* metrics) {
316     for (int i = 0; i < metrics->skipped_size(); ++i) {
317         backfillStartEndTimestampForPartialBucket(timeBaseNs, metrics->mutable_skipped(i));
318     }
319 }
320 }  // namespace statsd
321 }  // namespace os
322 }  // namespace android