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
26namespace android {
27namespace os {
28namespace statsd {
29
30using google::protobuf::RepeatedPtrField;
31
32// Create AtomMatcher proto to simply match a specific atom type.
33AtomMatcher CreateSimpleAtomMatcher(const string& name, int atomId);
34
35// Create AtomMatcher proto for temperature atom.
36AtomMatcher CreateTemperatureAtomMatcher();
37
38// Create AtomMatcher proto for scheduled job state changed.
39AtomMatcher CreateScheduledJobStateChangedAtomMatcher();
40
41// Create AtomMatcher proto for starting a scheduled job.
42AtomMatcher CreateStartScheduledJobAtomMatcher();
43
44// Create AtomMatcher proto for a scheduled job is done.
45AtomMatcher CreateFinishScheduledJobAtomMatcher();
46
47// Create AtomMatcher proto for screen brightness state changed.
48AtomMatcher CreateScreenBrightnessChangedAtomMatcher();
49
50// Create AtomMatcher proto for starting battery save mode.
51AtomMatcher CreateBatterySaverModeStartAtomMatcher();
52
53// Create AtomMatcher proto for stopping battery save mode.
54AtomMatcher CreateBatterySaverModeStopAtomMatcher();
55
56// Create AtomMatcher proto for process state changed.
57AtomMatcher CreateUidProcessStateChangedAtomMatcher();
58
59// Create AtomMatcher proto for acquiring wakelock.
60AtomMatcher CreateAcquireWakelockAtomMatcher();
61
62// Create AtomMatcher proto for releasing wakelock.
63AtomMatcher CreateReleaseWakelockAtomMatcher() ;
64
65// Create AtomMatcher proto for screen turned on.
66AtomMatcher CreateScreenTurnedOnAtomMatcher();
67
68// Create AtomMatcher proto for screen turned off.
69AtomMatcher CreateScreenTurnedOffAtomMatcher();
70
71// Create AtomMatcher proto for app sync turned on.
72AtomMatcher CreateSyncStartAtomMatcher();
73
74// Create AtomMatcher proto for app sync turned off.
75AtomMatcher CreateSyncEndAtomMatcher();
76
77// Create AtomMatcher proto for app sync moves to background.
78AtomMatcher CreateMoveToBackgroundAtomMatcher();
79
80// Create AtomMatcher proto for app sync moves to foreground.
81AtomMatcher CreateMoveToForegroundAtomMatcher();
82
83// Create AtomMatcher proto for process crashes
84AtomMatcher CreateProcessCrashAtomMatcher() ;
85
86// Create Predicate proto for screen is on.
87Predicate CreateScreenIsOnPredicate();
88
89// Create Predicate proto for screen is off.
90Predicate CreateScreenIsOffPredicate();
91
92// Create Predicate proto for a running scheduled job.
93Predicate CreateScheduledJobPredicate();
94
95// Create Predicate proto for battery saver mode.
96Predicate CreateBatterySaverModePredicate();
97
98// Create Predicate proto for holding wakelock.
99Predicate CreateHoldingWakelockPredicate();
100
101// Create a Predicate proto for app syncing.
102Predicate CreateIsSyncingPredicate();
103
104// Create a Predicate proto for app is in background.
105Predicate CreateIsInBackgroundPredicate();
106
107// Add a predicate to the predicate combination.
108void addPredicateToPredicateCombination(const Predicate& predicate, Predicate* combination);
109
110// Create dimensions from primitive fields.
111FieldMatcher CreateDimensions(const int atomId, const std::vector<int>& fields);
112
113// Create dimensions by attribution uid and tag.
114FieldMatcher CreateAttributionUidAndTagDimensions(const int atomId,
115                                                  const std::vector<Position>& positions);
116
117// Create dimensions by attribution uid only.
118FieldMatcher CreateAttributionUidDimensions(const int atomId,
119                                            const std::vector<Position>& positions);
120
121// Create log event for screen state changed.
122std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
123    const android::view::DisplayStateEnum state, uint64_t timestampNs);
124
125// Create log event for screen brightness state changed.
126std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(
127   int level, uint64_t timestampNs);
128
129// Create log event when scheduled job starts.
130std::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.
135std::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.
140std::unique_ptr<LogEvent> CreateBatterySaverOnEvent(uint64_t timestampNs);
141// Create log event when battery saver stops.
142std::unique_ptr<LogEvent> CreateBatterySaverOffEvent(uint64_t timestampNs);
143
144// Create log event for app moving to background.
145std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(const int uid, uint64_t timestampNs);
146
147// Create log event for app moving to foreground.
148std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(const int uid, uint64_t timestampNs);
149
150// Create log event when the app sync starts.
151std::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.
156std::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.
161std::unique_ptr<LogEvent> CreateAppCrashEvent(
162    const int uid, uint64_t timestampNs);
163
164// Create log event for acquiring wakelock.
165std::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.
170std::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.
175std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(
176    int isolatedUid, int hostUid, bool is_create, uint64_t timestampNs);
177
178// Helper function to create an AttributionNodeInternal proto.
179AttributionNodeInternal CreateAttribution(const int& uid, const string& tag);
180
181// Create a statsd log event processor upon the start time in seconds, config and key.
182sp<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.
187void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events);
188
189int64_t StringToId(const string& str);
190
191void ValidateUidDimension(const DimensionsValue& value, int node_idx, int atomId, int uid);
192void ValidateAttributionUidDimension(const DimensionsValue& value, int atomId, int uid);
193void ValidateAttributionUidAndTagDimension(
194    const DimensionsValue& value, int atomId, int uid, const std::string& tag);
195void ValidateAttributionUidAndTagDimension(
196    const DimensionsValue& value, int node_idx, int atomId, int uid, const std::string& tag);
197
198struct DimensionsPair {
199    DimensionsPair(DimensionsValue m1, DimensionsValue m2) : dimInWhat(m1), dimInCondition(m2){};
200
201    DimensionsValue dimInWhat;
202    DimensionsValue dimInCondition;
203};
204
205bool LessThan(const DimensionsValue& s1, const DimensionsValue& s2);
206bool LessThan(const DimensionsPair& s1, const DimensionsPair& s2);
207
208
209void backfillStartEndTimestamp(ConfigMetricsReport *config_report);
210void backfillStartEndTimestamp(ConfigMetricsReportList *config_report_list);
211
212void backfillStringInReport(ConfigMetricsReportList *config_report_list);
213void backfillStringInDimension(const std::map<uint64_t, string>& str_map,
214                               DimensionsValue* dimension);
215
216template <typename T>
217void 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
230void backfillDimensionPath(ConfigMetricsReportList* config_report_list);
231
232bool backfillDimensionPath(const DimensionsValue& path,
233                           const google::protobuf::RepeatedPtrField<DimensionsValue>& leafValues,
234                           DimensionsValue* dimension);
235
236template <typename T>
237void 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
255struct DimensionCompare {
256    bool operator()(const DimensionsPair& s1, const DimensionsPair& s2) const {
257        return LessThan(s1, s2);
258    }
259};
260
261template <typename T>
262void 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
275template <typename T>
276void 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
284template <typename T>
285void 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
298template <typename T>
299void 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
314template <typename T>
315void 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