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