// Copyright (C) 2017 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "statsd_test_util.h" #include #include #include #include #include "matchers/SimpleAtomMatchingTracker.h" #include "metrics/parsing_utils/histogram_parsing_utils.h" #include "stats_event.h" #include "stats_util.h" using aidl::android::util::StatsEventParcel; using android::base::SetProperty; using android::base::StringPrintf; using std::shared_ptr; using zetasketch::android::AggregatorStateProto; namespace android { namespace os { namespace statsd { bool StatsServiceConfigTest::sendConfig(const StatsdConfig& config) { string str; config.SerializeToString(&str); std::vector configAsVec(str.begin(), str.end()); return service->addConfiguration(kConfigKey, configAsVec, kCallingUid).isOk(); } ConfigMetricsReport StatsServiceConfigTest::getReports(sp processor, int64_t timestamp, bool include_current) { vector output; ConfigKey configKey(kCallingUid, kConfigKey); processor->onDumpReport(configKey, timestamp, include_current /* include_current_bucket*/, true /* erase_data */, ADB_DUMP, NO_TIME_CONSTRAINTS, &output); ConfigMetricsReportList reports; reports.ParseFromArray(output.data(), output.size()); EXPECT_EQ(1, reports.reports_size()); return reports.reports(0); } StatsLogReport outputStreamToProto(ProtoOutputStream* proto) { vector bytes; bytes.resize(proto->size()); size_t pos = 0; sp reader = proto->data(); while (reader->readBuffer() != NULL) { size_t toRead = reader->currentToRead(); std::memcpy(&((bytes)[pos]), reader->readBuffer(), toRead); pos += toRead; reader->move(toRead); } StatsLogReport report; report.ParseFromArray(bytes.data(), bytes.size()); return report; } AtomMatcher CreateSimpleAtomMatcher(const string& name, int atomId) { AtomMatcher atom_matcher; atom_matcher.set_id(StringToId(name)); auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); simple_atom_matcher->set_atom_id(atomId); return atom_matcher; } AtomMatcher CreateTemperatureAtomMatcher() { return CreateSimpleAtomMatcher("TemperatureMatcher", util::TEMPERATURE); } AtomMatcher CreateScheduledJobStateChangedAtomMatcher(const string& name, ScheduledJobStateChanged::State state) { AtomMatcher atom_matcher; atom_matcher.set_id(StringToId(name)); auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); simple_atom_matcher->set_atom_id(util::SCHEDULED_JOB_STATE_CHANGED); auto field_value_matcher = simple_atom_matcher->add_field_value_matcher(); field_value_matcher->set_field(3); // State field. field_value_matcher->set_eq_int(state); return atom_matcher; } AtomMatcher CreateStartScheduledJobAtomMatcher() { return CreateScheduledJobStateChangedAtomMatcher("ScheduledJobStart", ScheduledJobStateChanged::STARTED); } AtomMatcher CreateFinishScheduledJobAtomMatcher() { return CreateScheduledJobStateChangedAtomMatcher("ScheduledJobFinish", ScheduledJobStateChanged::FINISHED); } AtomMatcher CreateScheduleScheduledJobAtomMatcher() { return CreateScheduledJobStateChangedAtomMatcher("ScheduledJobSchedule", ScheduledJobStateChanged::SCHEDULED); } AtomMatcher CreateScreenBrightnessChangedAtomMatcher() { AtomMatcher atom_matcher; atom_matcher.set_id(StringToId("ScreenBrightnessChanged")); auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); simple_atom_matcher->set_atom_id(util::SCREEN_BRIGHTNESS_CHANGED); return atom_matcher; } AtomMatcher CreateUidProcessStateChangedAtomMatcher() { AtomMatcher atom_matcher; atom_matcher.set_id(StringToId("UidProcessStateChanged")); auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); simple_atom_matcher->set_atom_id(util::UID_PROCESS_STATE_CHANGED); return atom_matcher; } AtomMatcher CreateWakelockStateChangedAtomMatcher(const string& name, WakelockStateChanged::State state) { AtomMatcher atom_matcher; atom_matcher.set_id(StringToId(name)); auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); simple_atom_matcher->set_atom_id(util::WAKELOCK_STATE_CHANGED); auto field_value_matcher = simple_atom_matcher->add_field_value_matcher(); field_value_matcher->set_field(4); // State field. field_value_matcher->set_eq_int(state); return atom_matcher; } AtomMatcher CreateAcquireWakelockAtomMatcher() { return CreateWakelockStateChangedAtomMatcher("AcquireWakelock", WakelockStateChanged::ACQUIRE); } AtomMatcher CreateReleaseWakelockAtomMatcher() { return CreateWakelockStateChangedAtomMatcher("ReleaseWakelock", WakelockStateChanged::RELEASE); } AtomMatcher CreateBatterySaverModeStateChangedAtomMatcher( const string& name, BatterySaverModeStateChanged::State state) { AtomMatcher atom_matcher; atom_matcher.set_id(StringToId(name)); auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); simple_atom_matcher->set_atom_id(util::BATTERY_SAVER_MODE_STATE_CHANGED); auto field_value_matcher = simple_atom_matcher->add_field_value_matcher(); field_value_matcher->set_field(1); // State field. field_value_matcher->set_eq_int(state); return atom_matcher; } AtomMatcher CreateBatterySaverModeStartAtomMatcher() { return CreateBatterySaverModeStateChangedAtomMatcher( "BatterySaverModeStart", BatterySaverModeStateChanged::ON); } AtomMatcher CreateBatterySaverModeStopAtomMatcher() { return CreateBatterySaverModeStateChangedAtomMatcher( "BatterySaverModeStop", BatterySaverModeStateChanged::OFF); } AtomMatcher CreateBatteryStateChangedAtomMatcher(const string& name, BatteryPluggedStateEnum state) { AtomMatcher atom_matcher; atom_matcher.set_id(StringToId(name)); auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); simple_atom_matcher->set_atom_id(util::PLUGGED_STATE_CHANGED); auto field_value_matcher = simple_atom_matcher->add_field_value_matcher(); field_value_matcher->set_field(1); // State field. field_value_matcher->set_eq_int(state); return atom_matcher; } AtomMatcher CreateBatteryStateNoneMatcher() { return CreateBatteryStateChangedAtomMatcher("BatteryPluggedNone", BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE); } AtomMatcher CreateBatteryStateUsbMatcher() { return CreateBatteryStateChangedAtomMatcher("BatteryPluggedUsb", BatteryPluggedStateEnum::BATTERY_PLUGGED_USB); } AtomMatcher CreateScreenStateChangedAtomMatcher( const string& name, android::view::DisplayStateEnum state) { AtomMatcher atom_matcher; atom_matcher.set_id(StringToId(name)); auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); simple_atom_matcher->set_atom_id(util::SCREEN_STATE_CHANGED); auto field_value_matcher = simple_atom_matcher->add_field_value_matcher(); field_value_matcher->set_field(1); // State field. field_value_matcher->set_eq_int(state); return atom_matcher; } AtomMatcher CreateScreenTurnedOnAtomMatcher() { return CreateScreenStateChangedAtomMatcher("ScreenTurnedOn", android::view::DisplayStateEnum::DISPLAY_STATE_ON); } AtomMatcher CreateScreenTurnedOffAtomMatcher() { return CreateScreenStateChangedAtomMatcher("ScreenTurnedOff", ::android::view::DisplayStateEnum::DISPLAY_STATE_OFF); } AtomMatcher CreateSyncStateChangedAtomMatcher( const string& name, SyncStateChanged::State state) { AtomMatcher atom_matcher; atom_matcher.set_id(StringToId(name)); auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); simple_atom_matcher->set_atom_id(util::SYNC_STATE_CHANGED); auto field_value_matcher = simple_atom_matcher->add_field_value_matcher(); field_value_matcher->set_field(3); // State field. field_value_matcher->set_eq_int(state); return atom_matcher; } AtomMatcher CreateSyncStartAtomMatcher() { return CreateSyncStateChangedAtomMatcher("SyncStart", SyncStateChanged::ON); } AtomMatcher CreateSyncEndAtomMatcher() { return CreateSyncStateChangedAtomMatcher("SyncEnd", SyncStateChanged::OFF); } AtomMatcher CreateActivityForegroundStateChangedAtomMatcher( const string& name, ActivityForegroundStateChanged::State state) { AtomMatcher atom_matcher; atom_matcher.set_id(StringToId(name)); auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); simple_atom_matcher->set_atom_id(util::ACTIVITY_FOREGROUND_STATE_CHANGED); auto field_value_matcher = simple_atom_matcher->add_field_value_matcher(); field_value_matcher->set_field(4); // Activity field. field_value_matcher->set_eq_int(state); return atom_matcher; } AtomMatcher CreateMoveToBackgroundAtomMatcher() { return CreateActivityForegroundStateChangedAtomMatcher( "Background", ActivityForegroundStateChanged::BACKGROUND); } AtomMatcher CreateMoveToForegroundAtomMatcher() { return CreateActivityForegroundStateChangedAtomMatcher( "Foreground", ActivityForegroundStateChanged::FOREGROUND); } AtomMatcher CreateProcessLifeCycleStateChangedAtomMatcher( const string& name, ProcessLifeCycleStateChanged::State state) { AtomMatcher atom_matcher; atom_matcher.set_id(StringToId(name)); auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); simple_atom_matcher->set_atom_id(util::PROCESS_LIFE_CYCLE_STATE_CHANGED); auto field_value_matcher = simple_atom_matcher->add_field_value_matcher(); field_value_matcher->set_field(3); // Process state field. field_value_matcher->set_eq_int(state); return atom_matcher; } AtomMatcher CreateProcessCrashAtomMatcher() { return CreateProcessLifeCycleStateChangedAtomMatcher( "Crashed", ProcessLifeCycleStateChanged::CRASHED); } AtomMatcher CreateAppStartOccurredAtomMatcher() { return CreateSimpleAtomMatcher("AppStartOccurredMatcher", util::APP_START_OCCURRED); } AtomMatcher CreateTestAtomRepeatedStateAtomMatcher(const string& name, TestAtomReported::State state, Position position) { AtomMatcher atom_matcher = CreateSimpleAtomMatcher(name, util::TEST_ATOM_REPORTED); auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); auto field_value_matcher = simple_atom_matcher->add_field_value_matcher(); field_value_matcher->set_field(14); // Repeated enum field. field_value_matcher->set_eq_int(state); field_value_matcher->set_position(position); return atom_matcher; } AtomMatcher CreateTestAtomRepeatedStateFirstOffAtomMatcher() { return CreateTestAtomRepeatedStateAtomMatcher("TestFirstStateOff", TestAtomReported::OFF, Position::FIRST); } AtomMatcher CreateTestAtomRepeatedStateFirstOnAtomMatcher() { return CreateTestAtomRepeatedStateAtomMatcher("TestFirstStateOn", TestAtomReported::ON, Position::FIRST); } AtomMatcher CreateTestAtomRepeatedStateAnyOnAtomMatcher() { return CreateTestAtomRepeatedStateAtomMatcher("TestAnyStateOn", TestAtomReported::ON, Position::ANY); } void addMatcherToMatcherCombination(const AtomMatcher& matcher, AtomMatcher* combinationMatcher) { combinationMatcher->mutable_combination()->add_matcher(matcher.id()); } Predicate CreateScheduledJobPredicate() { Predicate predicate; predicate.set_id(StringToId("ScheduledJobRunningPredicate")); predicate.mutable_simple_predicate()->set_start(StringToId("ScheduledJobStart")); predicate.mutable_simple_predicate()->set_stop(StringToId("ScheduledJobFinish")); return predicate; } Predicate CreateBatterySaverModePredicate() { Predicate predicate; predicate.set_id(StringToId("BatterySaverIsOn")); predicate.mutable_simple_predicate()->set_start(StringToId("BatterySaverModeStart")); predicate.mutable_simple_predicate()->set_stop(StringToId("BatterySaverModeStop")); return predicate; } Predicate CreateDeviceUnpluggedPredicate() { Predicate predicate; predicate.set_id(StringToId("DeviceUnplugged")); predicate.mutable_simple_predicate()->set_start(StringToId("BatteryPluggedNone")); predicate.mutable_simple_predicate()->set_stop(StringToId("BatteryPluggedUsb")); return predicate; } Predicate CreateScreenIsOnPredicate() { Predicate predicate; predicate.set_id(StringToId("ScreenIsOn")); predicate.mutable_simple_predicate()->set_start(StringToId("ScreenTurnedOn")); predicate.mutable_simple_predicate()->set_stop(StringToId("ScreenTurnedOff")); return predicate; } Predicate CreateScreenIsOffPredicate() { Predicate predicate; predicate.set_id(StringToId("ScreenIsOff")); predicate.mutable_simple_predicate()->set_start(StringToId("ScreenTurnedOff")); predicate.mutable_simple_predicate()->set_stop(StringToId("ScreenTurnedOn")); return predicate; } Predicate CreateHoldingWakelockPredicate() { Predicate predicate; predicate.set_id(StringToId("HoldingWakelock")); predicate.mutable_simple_predicate()->set_start(StringToId("AcquireWakelock")); predicate.mutable_simple_predicate()->set_stop(StringToId("ReleaseWakelock")); return predicate; } Predicate CreateIsSyncingPredicate() { Predicate predicate; predicate.set_id(StringToId("IsSyncing")); predicate.mutable_simple_predicate()->set_start(StringToId("SyncStart")); predicate.mutable_simple_predicate()->set_stop(StringToId("SyncEnd")); return predicate; } Predicate CreateIsInBackgroundPredicate() { Predicate predicate; predicate.set_id(StringToId("IsInBackground")); predicate.mutable_simple_predicate()->set_start(StringToId("Background")); predicate.mutable_simple_predicate()->set_stop(StringToId("Foreground")); return predicate; } Predicate CreateTestAtomRepeatedStateFirstOffPredicate() { Predicate predicate; predicate.set_id(StringToId("TestFirstStateIsOff")); predicate.mutable_simple_predicate()->set_start(StringToId("TestFirstStateOff")); predicate.mutable_simple_predicate()->set_stop(StringToId("TestFirstStateOn")); return predicate; } State CreateScreenState() { State state; state.set_id(StringToId("ScreenState")); state.set_atom_id(util::SCREEN_STATE_CHANGED); return state; } State CreateUidProcessState() { State state; state.set_id(StringToId("UidProcessState")); state.set_atom_id(util::UID_PROCESS_STATE_CHANGED); return state; } State CreateOverlayState() { State state; state.set_id(StringToId("OverlayState")); state.set_atom_id(util::OVERLAY_STATE_CHANGED); return state; } State CreateScreenStateWithOnOffMap(int64_t screenOnId, int64_t screenOffId) { State state; state.set_id(StringToId("ScreenStateOnOff")); state.set_atom_id(util::SCREEN_STATE_CHANGED); auto map = CreateScreenStateOnOffMap(screenOnId, screenOffId); *state.mutable_map() = map; return state; } State CreateScreenStateWithSimpleOnOffMap(int64_t screenOnId, int64_t screenOffId) { State state; state.set_id(StringToId("ScreenStateSimpleOnOff")); state.set_atom_id(util::SCREEN_STATE_CHANGED); auto map = CreateScreenStateSimpleOnOffMap(screenOnId, screenOffId); *state.mutable_map() = map; return state; } StateMap_StateGroup CreateScreenStateOnGroup(int64_t screenOnId) { StateMap_StateGroup group; group.set_group_id(screenOnId); group.add_value(android::view::DisplayStateEnum::DISPLAY_STATE_ON); group.add_value(android::view::DisplayStateEnum::DISPLAY_STATE_VR); group.add_value(android::view::DisplayStateEnum::DISPLAY_STATE_ON_SUSPEND); return group; } StateMap_StateGroup CreateScreenStateOffGroup(int64_t screenOffId) { StateMap_StateGroup group; group.set_group_id(screenOffId); group.add_value(android::view::DisplayStateEnum::DISPLAY_STATE_OFF); group.add_value(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE); group.add_value(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE_SUSPEND); return group; } StateMap_StateGroup CreateScreenStateSimpleOnGroup(int64_t screenOnId) { StateMap_StateGroup group; group.set_group_id(screenOnId); group.add_value(android::view::DisplayStateEnum::DISPLAY_STATE_ON); return group; } StateMap_StateGroup CreateScreenStateSimpleOffGroup(int64_t screenOffId) { StateMap_StateGroup group; group.set_group_id(screenOffId); group.add_value(android::view::DisplayStateEnum::DISPLAY_STATE_OFF); return group; } StateMap CreateScreenStateOnOffMap(int64_t screenOnId, int64_t screenOffId) { StateMap map; *map.add_group() = CreateScreenStateOnGroup(screenOnId); *map.add_group() = CreateScreenStateOffGroup(screenOffId); return map; } StateMap CreateScreenStateSimpleOnOffMap(int64_t screenOnId, int64_t screenOffId) { StateMap map; *map.add_group() = CreateScreenStateSimpleOnGroup(screenOnId); *map.add_group() = CreateScreenStateSimpleOffGroup(screenOffId); return map; } void addPredicateToPredicateCombination(const Predicate& predicate, Predicate* combinationPredicate) { combinationPredicate->mutable_combination()->add_predicate(predicate.id()); } FieldMatcher CreateAttributionUidDimensions(const int atomId, const std::vector& positions) { FieldMatcher dimensions; dimensions.set_field(atomId); for (const auto position : positions) { auto child = dimensions.add_child(); child->set_field(1); child->set_position(position); child->add_child()->set_field(1); } return dimensions; } FieldMatcher CreateAttributionUidAndTagDimensions(const int atomId, const std::vector& positions) { FieldMatcher dimensions; dimensions.set_field(atomId); for (const auto position : positions) { auto child = dimensions.add_child(); child->set_field(1); child->set_position(position); child->add_child()->set_field(1); child->add_child()->set_field(2); } return dimensions; } FieldMatcher CreateDimensions(const int atomId, const std::vector& fields) { FieldMatcher dimensions; dimensions.set_field(atomId); for (const int field : fields) { dimensions.add_child()->set_field(field); } return dimensions; } FieldMatcher CreateRepeatedDimensions(const int atomId, const std::vector& fields, const std::vector& positions) { FieldMatcher dimensions; if (fields.size() != positions.size()) { return dimensions; } dimensions.set_field(atomId); for (size_t i = 0; i < fields.size(); i++) { auto child = dimensions.add_child(); child->set_field(fields[i]); child->set_position(positions[i]); } return dimensions; } FieldMatcher CreateAttributionUidAndOtherDimensions(const int atomId, const std::vector& positions, const std::vector& fields) { FieldMatcher dimensions = CreateAttributionUidDimensions(atomId, positions); for (const int field : fields) { dimensions.add_child()->set_field(field); } return dimensions; } EventMetric createEventMetric(const string& name, const int64_t what, const optional& condition) { EventMetric metric; metric.set_id(StringToId(name)); metric.set_what(what); if (condition) { metric.set_condition(condition.value()); } return metric; } CountMetric createCountMetric(const string& name, const int64_t what, const optional& condition, const vector& states) { CountMetric metric; metric.set_id(StringToId(name)); metric.set_what(what); metric.set_bucket(TEN_MINUTES); if (condition) { metric.set_condition(condition.value()); } for (const int64_t state : states) { metric.add_slice_by_state(state); } return metric; } DurationMetric createDurationMetric(const string& name, const int64_t what, const optional& condition, const vector& states) { DurationMetric metric; metric.set_id(StringToId(name)); metric.set_what(what); metric.set_bucket(TEN_MINUTES); if (condition) { metric.set_condition(condition.value()); } for (const int64_t state : states) { metric.add_slice_by_state(state); } return metric; } GaugeMetric createGaugeMetric(const string& name, const int64_t what, const GaugeMetric::SamplingType samplingType, const optional& condition, const optional& triggerEvent) { GaugeMetric metric; metric.set_id(StringToId(name)); metric.set_what(what); metric.set_bucket(TEN_MINUTES); metric.set_sampling_type(samplingType); if (condition) { metric.set_condition(condition.value()); } if (triggerEvent) { metric.set_trigger_event(triggerEvent.value()); } metric.mutable_gauge_fields_filter()->set_include_all(true); return metric; } ValueMetric createValueMetric(const string& name, const AtomMatcher& what, const int valueField, const optional& condition, const vector& states) { return createValueMetric(name, what, {valueField}, /* aggregationTypes */ {}, condition, states); } ValueMetric createValueMetric(const string& name, const AtomMatcher& what, const vector& valueFields, const vector& aggregationTypes, const optional& condition, const vector& states) { ValueMetric metric; metric.set_id(StringToId(name)); metric.set_what(what.id()); metric.set_bucket(TEN_MINUTES); metric.mutable_value_field()->set_field(what.simple_atom_matcher().atom_id()); for (int valueField : valueFields) { metric.mutable_value_field()->add_child()->set_field(valueField); } for (const ValueMetric::AggregationType aggType : aggregationTypes) { metric.add_aggregation_types(aggType); } if (condition) { metric.set_condition(condition.value()); } for (const int64_t state : states) { metric.add_slice_by_state(state); } return metric; } HistogramBinConfig createGeneratedBinConfig(int id, float min, float max, int count, HistogramBinConfig::GeneratedBins::Strategy strategy) { HistogramBinConfig binConfig; binConfig.set_id(id); binConfig.mutable_generated_bins()->set_min(min); binConfig.mutable_generated_bins()->set_max(max); binConfig.mutable_generated_bins()->set_count(count); binConfig.mutable_generated_bins()->set_strategy(strategy); return binConfig; } HistogramBinConfig createExplicitBinConfig(int id, const vector& bins) { HistogramBinConfig binConfig; binConfig.set_id(id); *binConfig.mutable_explicit_bins()->mutable_bin() = {bins.begin(), bins.end()}; return binConfig; } KllMetric createKllMetric(const string& name, const AtomMatcher& what, const int kllField, const optional& condition) { KllMetric metric; metric.set_id(StringToId(name)); metric.set_what(what.id()); metric.set_bucket(TEN_MINUTES); metric.mutable_kll_field()->set_field(what.simple_atom_matcher().atom_id()); metric.mutable_kll_field()->add_child()->set_field(kllField); if (condition) { metric.set_condition(condition.value()); } return metric; } Alert createAlert(const string& name, const int64_t metricId, const int buckets, const int64_t triggerSum) { Alert alert; alert.set_id(StringToId(name)); alert.set_metric_id(metricId); alert.set_num_buckets(buckets); alert.set_trigger_if_sum_gt(triggerSum); return alert; } Alarm createAlarm(const string& name, const int64_t offsetMillis, const int64_t periodMillis) { Alarm alarm; alarm.set_id(StringToId(name)); alarm.set_offset_millis(offsetMillis); alarm.set_period_millis(periodMillis); return alarm; } Subscription createSubscription(const string& name, const Subscription_RuleType type, const int64_t ruleId) { Subscription subscription; subscription.set_id(StringToId(name)); subscription.set_rule_type(type); subscription.set_rule_id(ruleId); subscription.mutable_broadcast_subscriber_details(); return subscription; } // START: get primary key functions void getUidProcessKey(int uid, HashableDimensionKey* key) { int pos1[] = {1, 0, 0}; Field field1(27 /* atom id */, pos1, 0 /* depth */); Value value1((int32_t)uid); key->addValue(FieldValue(field1, value1)); } void getOverlayKey(int uid, string packageName, HashableDimensionKey* key) { int pos1[] = {1, 0, 0}; int pos2[] = {2, 0, 0}; Field field1(59 /* atom id */, pos1, 0 /* depth */); Field field2(59 /* atom id */, pos2, 0 /* depth */); Value value1((int32_t)uid); Value value2(packageName); key->addValue(FieldValue(field1, value1)); key->addValue(FieldValue(field2, value2)); } void getPartialWakelockKey(int uid, const std::string& tag, HashableDimensionKey* key) { int pos1[] = {1, 1, 1}; int pos3[] = {2, 0, 0}; int pos4[] = {3, 0, 0}; Field field1(10 /* atom id */, pos1, 2 /* depth */); Field field3(10 /* atom id */, pos3, 0 /* depth */); Field field4(10 /* atom id */, pos4, 0 /* depth */); Value value1((int32_t)uid); Value value3((int32_t)1 /*partial*/); Value value4(tag); key->addValue(FieldValue(field1, value1)); key->addValue(FieldValue(field3, value3)); key->addValue(FieldValue(field4, value4)); } void getPartialWakelockKey(int uid, HashableDimensionKey* key) { int pos1[] = {1, 1, 1}; int pos3[] = {2, 0, 0}; Field field1(10 /* atom id */, pos1, 2 /* depth */); Field field3(10 /* atom id */, pos3, 0 /* depth */); Value value1((int32_t)uid); Value value3((int32_t)1 /*partial*/); key->addValue(FieldValue(field1, value1)); key->addValue(FieldValue(field3, value3)); } // END: get primary key functions void writeAttribution(AStatsEvent* statsEvent, const vector& attributionUids, const vector& attributionTags) { vector cTags(attributionTags.size()); for (int i = 0; i < cTags.size(); i++) { cTags[i] = attributionTags[i].c_str(); } AStatsEvent_writeAttributionChain(statsEvent, reinterpret_cast(attributionUids.data()), cTags.data(), attributionUids.size()); } bool parseStatsEventToLogEvent(AStatsEvent* statsEvent, LogEvent* logEvent) { AStatsEvent_build(statsEvent); size_t size; uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); const bool result = logEvent->parseBuffer(buf, size); AStatsEvent_release(statsEvent); return result; } AStatsEvent* makeTwoValueStatsEvent(int atomId, int64_t eventTimeNs, int32_t value1, int32_t value2) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, atomId); AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs); AStatsEvent_writeInt32(statsEvent, value1); AStatsEvent_writeInt32(statsEvent, value2); return statsEvent; } void CreateTwoValueLogEvent(LogEvent* logEvent, int atomId, int64_t eventTimeNs, int32_t value1, int32_t value2) { AStatsEvent* statsEvent = makeTwoValueStatsEvent(atomId, eventTimeNs, value1, value2); parseStatsEventToLogEvent(statsEvent, logEvent); } shared_ptr CreateTwoValueLogEvent(int atomId, int64_t eventTimeNs, int32_t value1, int32_t value2) { shared_ptr logEvent = std::make_shared(/*uid=*/0, /*pid=*/0); CreateTwoValueLogEvent(logEvent.get(), atomId, eventTimeNs, value1, value2); return logEvent; } void CreateThreeValueLogEvent(LogEvent* logEvent, int atomId, int64_t eventTimeNs, int32_t value1, int32_t value2, int32_t value3) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, atomId); AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs); AStatsEvent_writeInt32(statsEvent, value1); AStatsEvent_writeInt32(statsEvent, value2); AStatsEvent_writeInt32(statsEvent, value3); parseStatsEventToLogEvent(statsEvent, logEvent); } shared_ptr CreateThreeValueLogEvent(int atomId, int64_t eventTimeNs, int32_t value1, int32_t value2, int32_t value3) { shared_ptr logEvent = std::make_shared(/*uid=*/0, /*pid=*/0); CreateThreeValueLogEvent(logEvent.get(), atomId, eventTimeNs, value1, value2, value3); return logEvent; } void CreateRepeatedValueLogEvent(LogEvent* logEvent, int atomId, int64_t eventTimeNs, int32_t value) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, atomId); AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs); AStatsEvent_writeInt32(statsEvent, value); AStatsEvent_writeInt32(statsEvent, value); parseStatsEventToLogEvent(statsEvent, logEvent); } shared_ptr CreateRepeatedValueLogEvent(int atomId, int64_t eventTimeNs, int32_t value) { shared_ptr logEvent = std::make_shared(/*uid=*/0, /*pid=*/0); CreateRepeatedValueLogEvent(logEvent.get(), atomId, eventTimeNs, value); return logEvent; } void CreateNoValuesLogEvent(LogEvent* logEvent, int atomId, int64_t eventTimeNs) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, atomId); AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs); parseStatsEventToLogEvent(statsEvent, logEvent); } shared_ptr CreateNoValuesLogEvent(int atomId, int64_t eventTimeNs) { shared_ptr logEvent = std::make_shared(/*uid=*/0, /*pid=*/0); CreateNoValuesLogEvent(logEvent.get(), atomId, eventTimeNs); return logEvent; } AStatsEvent* makeUidStatsEvent(int atomId, int64_t eventTimeNs, int uid, int data1, int data2) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, atomId); AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs); AStatsEvent_writeInt32(statsEvent, uid); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_IS_UID, true); AStatsEvent_writeInt32(statsEvent, data1); AStatsEvent_writeInt32(statsEvent, data2); return statsEvent; } AStatsEvent* makeUidStatsEvent(int atomId, int64_t eventTimeNs, int uid, int data1, const vector& data2) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, atomId); AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs); AStatsEvent_writeInt32(statsEvent, uid); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_IS_UID, true); AStatsEvent_writeInt32(statsEvent, data1); AStatsEvent_writeInt32Array(statsEvent, data2.data(), data2.size()); return statsEvent; } AStatsEvent* makeAttributionStatsEvent(int atomId, int64_t eventTimeNs, const vector& uids, const vector& tags, int data1, int data2) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, atomId); AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs); writeAttribution(statsEvent, uids, tags); AStatsEvent_writeInt32(statsEvent, data1); AStatsEvent_writeInt32(statsEvent, data2); return statsEvent; } shared_ptr makeUidLogEvent(int atomId, int64_t eventTimeNs, int uid, int data1, int data2) { AStatsEvent* statsEvent = makeUidStatsEvent(atomId, eventTimeNs, uid, data1, data2); shared_ptr logEvent = std::make_shared(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } shared_ptr makeUidLogEvent(int atomId, int64_t eventTimeNs, int uid, int data1, const vector& data2) { AStatsEvent* statsEvent = makeUidStatsEvent(atomId, eventTimeNs, uid, data1, data2); shared_ptr logEvent = std::make_shared(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } shared_ptr makeExtraUidsLogEvent(int atomId, int64_t eventTimeNs, int uid1, int data1, int data2, const vector& extraUids) { AStatsEvent* statsEvent = makeUidStatsEvent(atomId, eventTimeNs, uid1, data1, data2); for (const int extraUid : extraUids) { AStatsEvent_writeInt32(statsEvent, extraUid); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_IS_UID, true); } shared_ptr logEvent = std::make_shared(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } shared_ptr makeRepeatedUidLogEvent(int atomId, int64_t eventTimeNs, const vector& uids) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, atomId); AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs); AStatsEvent_writeInt32Array(statsEvent, uids.data(), uids.size()); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_IS_UID, true); shared_ptr logEvent = std::make_shared(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } shared_ptr makeRepeatedUidLogEvent(int atomId, int64_t eventTimeNs, const vector& uids, int data1, int data2) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, atomId); AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs); AStatsEvent_writeInt32Array(statsEvent, uids.data(), uids.size()); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_IS_UID, true); AStatsEvent_writeInt32(statsEvent, data1); AStatsEvent_writeInt32(statsEvent, data2); shared_ptr logEvent = std::make_shared(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } shared_ptr makeRepeatedUidLogEvent(int atomId, int64_t eventTimeNs, const vector& uids, int data1, const vector& data2) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, atomId); AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs); AStatsEvent_writeInt32Array(statsEvent, uids.data(), uids.size()); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_IS_UID, true); AStatsEvent_writeInt32(statsEvent, data1); AStatsEvent_writeInt32Array(statsEvent, data2.data(), data2.size()); shared_ptr logEvent = std::make_shared(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } shared_ptr makeAttributionLogEvent(int atomId, int64_t eventTimeNs, const vector& uids, const vector& tags, int data1, int data2) { AStatsEvent* statsEvent = makeAttributionStatsEvent(atomId, eventTimeNs, uids, tags, data1, data2); shared_ptr logEvent = std::make_shared(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } sp makeMockUidMapForHosts(const map>& hostUidToIsolatedUidsMap) { sp uidMap = new NaggyMock(); EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(ReturnArg<0>()); for (const auto& [hostUid, isolatedUids] : hostUidToIsolatedUidsMap) { for (const int isolatedUid : isolatedUids) { EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid)).WillRepeatedly(Return(hostUid)); } } return uidMap; } sp makeMockUidMapForPackage(const string& pkg, const set& uids) { sp uidMap = new StrictMock(); EXPECT_CALL(*uidMap, getAppUid(_)).Times(AnyNumber()); EXPECT_CALL(*uidMap, getAppUid(pkg)).WillRepeatedly(Return(uids)); return uidMap; } std::unique_ptr CreateScreenStateChangedEvent(uint64_t timestampNs, const android::view::DisplayStateEnum state, int loggerUid) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::SCREEN_STATE_CHANGED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); AStatsEvent_writeInt32(statsEvent, state); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, true); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_STATE_NESTED, false); std::unique_ptr logEvent = std::make_unique(loggerUid, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateBatterySaverOnEvent(uint64_t timestampNs) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::BATTERY_SAVER_MODE_STATE_CHANGED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); AStatsEvent_writeInt32(statsEvent, BatterySaverModeStateChanged::ON); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, true); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_STATE_NESTED, false); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateBatterySaverOffEvent(uint64_t timestampNs) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::BATTERY_SAVER_MODE_STATE_CHANGED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); AStatsEvent_writeInt32(statsEvent, BatterySaverModeStateChanged::OFF); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, true); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_STATE_NESTED, false); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateBatteryStateChangedEvent(const uint64_t timestampNs, const BatteryPluggedStateEnum state, int32_t uid) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::PLUGGED_STATE_CHANGED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); AStatsEvent_writeInt32(statsEvent, state); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, true); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_STATE_NESTED, false); std::unique_ptr logEvent = std::make_unique(/*uid=*/uid, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateMalformedBatteryStateChangedEvent(const uint64_t timestampNs) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::PLUGGED_STATE_CHANGED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); AStatsEvent_writeString(statsEvent, "bad_state"); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, true); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_STATE_NESTED, false); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateScreenBrightnessChangedEvent(uint64_t timestampNs, int level) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::SCREEN_BRIGHTNESS_CHANGED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); AStatsEvent_writeInt32(statsEvent, level); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateScheduledJobStateChangedEvent( const vector& attributionUids, const vector& attributionTags, const string& jobName, const ScheduledJobStateChanged::State state, uint64_t timestampNs) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::SCHEDULED_JOB_STATE_CHANGED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); writeAttribution(statsEvent, attributionUids, attributionTags); AStatsEvent_writeString(statsEvent, jobName.c_str()); AStatsEvent_writeInt32(statsEvent, state); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateStartScheduledJobEvent(uint64_t timestampNs, const vector& attributionUids, const vector& attributionTags, const string& jobName) { return CreateScheduledJobStateChangedEvent(attributionUids, attributionTags, jobName, ScheduledJobStateChanged::STARTED, timestampNs); } // Create log event when scheduled job finishes. std::unique_ptr CreateFinishScheduledJobEvent(uint64_t timestampNs, const vector& attributionUids, const vector& attributionTags, const string& jobName) { return CreateScheduledJobStateChangedEvent(attributionUids, attributionTags, jobName, ScheduledJobStateChanged::FINISHED, timestampNs); } // Create log event when scheduled job is scheduled. std::unique_ptr CreateScheduleScheduledJobEvent(uint64_t timestampNs, const vector& attributionUids, const vector& attributionTags, const string& jobName) { return CreateScheduledJobStateChangedEvent(attributionUids, attributionTags, jobName, ScheduledJobStateChanged::SCHEDULED, timestampNs); } std::unique_ptr CreateTestAtomReportedEventVariableRepeatedFields( uint64_t timestampNs, const vector& repeatedIntField, const vector& repeatedLongField, const vector& repeatedFloatField, const vector& repeatedStringField, const bool* repeatedBoolField, const size_t repeatedBoolFieldLength, const vector& repeatedEnumField) { return CreateTestAtomReportedEvent(timestampNs, {1001, 1002}, {"app1", "app2"}, 5, 1000l, 21.9f, "string", 1, TestAtomReported::ON, {8, 1, 8, 2, 8, 3}, repeatedIntField, repeatedLongField, repeatedFloatField, repeatedStringField, repeatedBoolField, repeatedBoolFieldLength, repeatedEnumField); } std::unique_ptr CreateTestAtomReportedEventWithPrimitives( uint64_t timestampNs, int intField, long longField, float floatField, const string& stringField, bool boolField, TestAtomReported::State enumField) { return CreateTestAtomReportedEvent( timestampNs, /* attributionUids */ {1001}, /* attributionTags */ {"app1"}, intField, longField, floatField, stringField, boolField, enumField, /* bytesField */ {}, /* repeatedIntField */ {}, /* repeatedLongField */ {}, /* repeatedFloatField */ {}, /* repeatedStringField */ {}, /* repeatedBoolField */ {}, /* repeatedBoolFieldLength */ 0, /* repeatedEnumField */ {}); } std::unique_ptr CreateTestAtomReportedEvent( uint64_t timestampNs, const vector& attributionUids, const vector& attributionTags, const int intField, const long longField, const float floatField, const string& stringField, const bool boolField, const TestAtomReported::State enumField, const vector& bytesField, const vector& repeatedIntField, const vector& repeatedLongField, const vector& repeatedFloatField, const vector& repeatedStringField, const bool* repeatedBoolField, const size_t repeatedBoolFieldLength, const vector& repeatedEnumField) { vector cRepeatedStringField(repeatedStringField.size()); for (int i = 0; i < cRepeatedStringField.size(); i++) { cRepeatedStringField[i] = repeatedStringField[i].c_str(); } AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::TEST_ATOM_REPORTED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); writeAttribution(statsEvent, attributionUids, attributionTags); AStatsEvent_writeInt32(statsEvent, intField); AStatsEvent_writeInt64(statsEvent, longField); AStatsEvent_writeFloat(statsEvent, floatField); AStatsEvent_writeString(statsEvent, stringField.c_str()); AStatsEvent_writeBool(statsEvent, boolField); AStatsEvent_writeInt32(statsEvent, enumField); AStatsEvent_writeByteArray(statsEvent, bytesField.data(), bytesField.size()); if (__builtin_available(android __ANDROID_API_T__, *)) { /* CreateTestAtomReportedEvent is used in CreateTestAtomReportedEventVariableRepeatedFields and CreateTestAtomReportedEventWithPrimitives. Only CreateTestAtomReportedEventVariableRepeatedFields writes repeated fields, so wrapping this portion in a __builtin_available and CreateTestAtomReportedEventVariableRepeatedFields is annotated with __INTRODUCED_IN. */ AStatsEvent_writeInt32Array(statsEvent, repeatedIntField.data(), repeatedIntField.size()); AStatsEvent_writeInt64Array(statsEvent, repeatedLongField.data(), repeatedLongField.size()); AStatsEvent_writeFloatArray(statsEvent, repeatedFloatField.data(), repeatedFloatField.size()); AStatsEvent_writeStringArray(statsEvent, cRepeatedStringField.data(), repeatedStringField.size()); AStatsEvent_writeBoolArray(statsEvent, repeatedBoolField, repeatedBoolFieldLength); AStatsEvent_writeInt32Array(statsEvent, repeatedEnumField.data(), repeatedEnumField.size()); } else if (!repeatedIntField.empty() || !repeatedLongField.empty() || !repeatedFloatField.empty() || !cRepeatedStringField.empty() || repeatedBoolFieldLength != 0 || !repeatedEnumField.empty()) { ADD_FAILURE() << "CreateTestAtomReportedEvent w/ repeated fields is only available in " "Android T and above."; } std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateWakelockStateChangedEvent(uint64_t timestampNs, const vector& attributionUids, const vector& attributionTags, const string& wakelockName, const WakelockStateChanged::State state) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::WAKELOCK_STATE_CHANGED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); writeAttribution(statsEvent, attributionUids, attributionTags); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, true); AStatsEvent_writeInt32(statsEvent, android::os::WakeLockLevelEnum::PARTIAL_WAKE_LOCK); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, true); AStatsEvent_writeString(statsEvent, wakelockName.c_str()); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, true); AStatsEvent_writeInt32(statsEvent, state); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, true); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_STATE_NESTED, true); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateAcquireWakelockEvent(uint64_t timestampNs, const vector& attributionUids, const vector& attributionTags, const string& wakelockName) { return CreateWakelockStateChangedEvent(timestampNs, attributionUids, attributionTags, wakelockName, WakelockStateChanged::ACQUIRE); } std::unique_ptr CreateReleaseWakelockEvent(uint64_t timestampNs, const vector& attributionUids, const vector& attributionTags, const string& wakelockName) { return CreateWakelockStateChangedEvent(timestampNs, attributionUids, attributionTags, wakelockName, WakelockStateChanged::RELEASE); } std::unique_ptr CreateActivityForegroundStateChangedEvent( uint64_t timestampNs, const int uid, const string& pkgName, const string& className, const ActivityForegroundStateChanged::State state) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::ACTIVITY_FOREGROUND_STATE_CHANGED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); AStatsEvent_writeInt32(statsEvent, uid); AStatsEvent_writeString(statsEvent, pkgName.c_str()); AStatsEvent_writeString(statsEvent, className.c_str()); AStatsEvent_writeInt32(statsEvent, state); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateMoveToBackgroundEvent(uint64_t timestampNs, const int uid) { return CreateActivityForegroundStateChangedEvent(timestampNs, uid, "pkg_name", "class_name", ActivityForegroundStateChanged::BACKGROUND); } std::unique_ptr CreateMoveToForegroundEvent(uint64_t timestampNs, const int uid) { return CreateActivityForegroundStateChangedEvent(timestampNs, uid, "pkg_name", "class_name", ActivityForegroundStateChanged::FOREGROUND); } std::unique_ptr CreateSyncStateChangedEvent(uint64_t timestampNs, const vector& attributionUids, const vector& attributionTags, const string& name, const SyncStateChanged::State state) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::SYNC_STATE_CHANGED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); writeAttribution(statsEvent, attributionUids, attributionTags); AStatsEvent_writeString(statsEvent, name.c_str()); AStatsEvent_writeInt32(statsEvent, state); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateSyncStartEvent(uint64_t timestampNs, const vector& attributionUids, const vector& attributionTags, const string& name) { return CreateSyncStateChangedEvent(timestampNs, attributionUids, attributionTags, name, SyncStateChanged::ON); } std::unique_ptr CreateSyncEndEvent(uint64_t timestampNs, const vector& attributionUids, const vector& attributionTags, const string& name) { return CreateSyncStateChangedEvent(timestampNs, attributionUids, attributionTags, name, SyncStateChanged::OFF); } std::unique_ptr CreateProcessLifeCycleStateChangedEvent( uint64_t timestampNs, const int uid, const ProcessLifeCycleStateChanged::State state) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::PROCESS_LIFE_CYCLE_STATE_CHANGED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); AStatsEvent_writeInt32(statsEvent, uid); AStatsEvent_writeString(statsEvent, ""); AStatsEvent_writeInt32(statsEvent, state); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateAppCrashEvent(uint64_t timestampNs, const int uid) { return CreateProcessLifeCycleStateChangedEvent(timestampNs, uid, ProcessLifeCycleStateChanged::CRASHED); } std::unique_ptr CreateAppCrashOccurredEvent(uint64_t timestampNs, const int uid) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::APP_CRASH_OCCURRED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); AStatsEvent_writeInt32(statsEvent, uid); AStatsEvent_writeString(statsEvent, "eventType"); AStatsEvent_writeString(statsEvent, "processName"); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateIsolatedUidChangedEvent(uint64_t timestampNs, int hostUid, int isolatedUid, bool is_create) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::ISOLATED_UID_CHANGED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); AStatsEvent_writeInt32(statsEvent, hostUid); AStatsEvent_writeInt32(statsEvent, isolatedUid); AStatsEvent_writeInt32(statsEvent, is_create); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateUidProcessStateChangedEvent( uint64_t timestampNs, int uid, const android::app::ProcessStateEnum state) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::UID_PROCESS_STATE_CHANGED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); AStatsEvent_writeInt32(statsEvent, uid); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_IS_UID, true); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, true); AStatsEvent_writeInt32(statsEvent, state); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, true); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_STATE_NESTED, false); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateBleScanStateChangedEvent(uint64_t timestampNs, const vector& attributionUids, const vector& attributionTags, const BleScanStateChanged::State state, const bool filtered, const bool firstMatch, const bool opportunistic) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::BLE_SCAN_STATE_CHANGED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); writeAttribution(statsEvent, attributionUids, attributionTags); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, true); AStatsEvent_writeInt32(statsEvent, state); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, true); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_STATE_NESTED, true); if (state == util::BLE_SCAN_STATE_CHANGED__STATE__RESET) { AStatsEvent_addInt32Annotation(statsEvent, ASTATSLOG_ANNOTATION_ID_TRIGGER_STATE_RESET, util::BLE_SCAN_STATE_CHANGED__STATE__OFF); } AStatsEvent_writeBool(statsEvent, filtered); // filtered AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, true); AStatsEvent_writeBool(statsEvent, firstMatch); // first match AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, true); AStatsEvent_writeBool(statsEvent, opportunistic); // opportunistic AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, true); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateOverlayStateChangedEvent(int64_t timestampNs, const int32_t uid, const string& packageName, const bool usingAlertWindow, const OverlayStateChanged::State state) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::OVERLAY_STATE_CHANGED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); AStatsEvent_writeInt32(statsEvent, uid); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_IS_UID, true); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, true); AStatsEvent_writeString(statsEvent, packageName.c_str()); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, true); AStatsEvent_writeBool(statsEvent, usingAlertWindow); AStatsEvent_writeInt32(statsEvent, state); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, true); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_STATE_NESTED, false); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateAppStartOccurredEvent( uint64_t timestampNs, const int uid, const string& pkgName, AppStartOccurred::TransitionType type, const string& activityName, const string& callingPkgName, const bool isInstantApp, int64_t activityStartMs) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::APP_START_OCCURRED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); AStatsEvent_writeInt32(statsEvent, uid); AStatsEvent_writeString(statsEvent, pkgName.c_str()); AStatsEvent_writeInt32(statsEvent, type); AStatsEvent_writeString(statsEvent, activityName.c_str()); AStatsEvent_writeString(statsEvent, callingPkgName.c_str()); AStatsEvent_writeInt32(statsEvent, isInstantApp); AStatsEvent_writeInt32(statsEvent, activityStartMs); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateBleScanResultReceivedEvent(uint64_t timestampNs, const vector& attributionUids, const vector& attributionTags, const int numResults) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::BLE_SCAN_RESULT_RECEIVED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); writeAttribution(statsEvent, attributionUids, attributionTags); AStatsEvent_writeInt32(statsEvent, numResults); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateRestrictedLogEvent(int atomTag, int64_t timestampNs) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, atomTag); AStatsEvent_addInt32Annotation(statsEvent, ASTATSLOG_ANNOTATION_ID_RESTRICTION_CATEGORY, ASTATSLOG_RESTRICTION_CATEGORY_DIAGNOSTIC); AStatsEvent_writeInt32(statsEvent, 10); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreateNonRestrictedLogEvent(int atomTag, int64_t timestampNs) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, atomTag); AStatsEvent_writeInt32(statsEvent, 10); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } std::unique_ptr CreatePhoneSignalStrengthChangedEvent( int64_t timestampNs, ::telephony::SignalStrengthEnum state) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::PHONE_SIGNAL_STRENGTH_CHANGED); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_TRUNCATE_TIMESTAMP, true); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); AStatsEvent_writeInt32(statsEvent, state); std::unique_ptr logEvent = std::make_unique(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } sp CreateStatsLogProcessor(const int64_t timeBaseNs, const int64_t currentTimeNs, const StatsdConfig& config, const ConfigKey& key, const shared_ptr& puller, const int32_t atomTag, const sp uidMap, const shared_ptr& logEventFilter) { sp pullerManager = new StatsPullerManager(); StatsPuller::SetUidMap(uidMap); if (puller != nullptr) { pullerManager->RegisterPullAtomCallback(/*uid=*/0, atomTag, NS_PER_SEC, NS_PER_SEC * 10, {}, puller); } sp anomalyAlarmMonitor = new AlarmMonitor(1, [](const shared_ptr&, int64_t){}, [](const shared_ptr&){}); sp periodicAlarmMonitor = new AlarmMonitor(1, [](const shared_ptr&, int64_t){}, [](const shared_ptr&){}); sp processor = new StatsLogProcessor( uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, timeBaseNs, [](const ConfigKey&) { return true; }, [](const int&, const vector&) { return true; }, [](const ConfigKey&, const string&, const vector&) {}, logEventFilter); processor->OnConfigUpdated(currentTimeNs, key, config); return processor; } sp createNumericValueMetricProducer( sp& pullerManager, const ValueMetric& metric, const int atomId, bool isPulled, const ConfigKey& configKey, const uint64_t protoHash, const int64_t timeBaseNs, const int64_t startTimeNs, const int logEventMatcherIndex, optional conditionAfterFirstBucketPrepared, vector slicedStateAtoms, unordered_map> stateGroupMap, sp eventMatcherWizard) { if (eventMatcherWizard == nullptr) { eventMatcherWizard = createEventMatcherWizard(atomId, logEventMatcherIndex); } sp wizard = new NaggyMock(); if (isPulled) { EXPECT_CALL(*pullerManager, RegisterReceiver(atomId, configKey, _, _, _)) .WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(atomId, configKey, _)) .WillRepeatedly(Return()); } const int64_t bucketSizeNs = MillisToNano( TimeUnitToBucketSizeInMillisGuardrailed(configKey.GetUid(), metric.bucket())); const bool containsAnyPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what()); const bool shouldUseNestedDimensions = ShouldUseNestedDimensions(metric.dimensions_in_what()); vector fieldMatchers; translateFieldMatcher(metric.value_field(), &fieldMatchers); const auto [dimensionSoftLimit, dimensionHardLimit] = StatsdStats::getAtomDimensionKeySizeLimits(atomId, StatsdStats::kDimensionKeySizeHardLimitMin); int conditionIndex = conditionAfterFirstBucketPrepared ? 0 : -1; vector initialConditionCache; if (conditionAfterFirstBucketPrepared) { initialConditionCache.push_back(ConditionState::kUnknown); } // get the condition_correction_threshold_nanos value const optional conditionCorrectionThresholdNs = metric.has_condition_correction_threshold_nanos() ? optional(metric.condition_correction_threshold_nanos()) : nullopt; std::vector aggregationTypes; if (metric.aggregation_types_size() != 0) { for (int i = 0; i < metric.aggregation_types_size(); i++) { aggregationTypes.push_back(metric.aggregation_types(i)); } } else { // aggregation_type() is set or default is used. aggregationTypes.push_back(metric.aggregation_type()); } ParseHistogramBinConfigsResult parseBinConfigsResult = parseHistogramBinConfigs(metric, aggregationTypes); const vector>& binStartsList = std::get>>(parseBinConfigsResult); sp provider = makeMockConfigMetadataProvider(/*enabled=*/false); const int pullAtomId = isPulled ? atomId : -1; return new NumericValueMetricProducer( configKey, metric, protoHash, {pullAtomId, pullerManager}, {timeBaseNs, startTimeNs, bucketSizeNs, metric.min_bucket_size_nanos(), conditionCorrectionThresholdNs, metric.split_bucket_for_app_upgrade()}, {containsAnyPositionInDimensionsInWhat, shouldUseNestedDimensions, logEventMatcherIndex, eventMatcherWizard, metric.dimensions_in_what(), fieldMatchers, aggregationTypes, binStartsList}, {conditionIndex, metric.links(), initialConditionCache, wizard}, {metric.state_link(), slicedStateAtoms, stateGroupMap}, {/*eventActivationMap=*/{}, /*eventDeactivationMap=*/{}}, {dimensionSoftLimit, dimensionHardLimit}, provider); } LogEventFilter::AtomIdSet CreateAtomIdSetDefault() { LogEventFilter::AtomIdSet resultList(StatsLogProcessor::getDefaultAtomIdSet()); StateManager::getInstance().addAllAtomIds(resultList); return resultList; } LogEventFilter::AtomIdSet CreateAtomIdSetFromConfig(const StatsdConfig& config) { LogEventFilter::AtomIdSet resultList(StatsLogProcessor::getDefaultAtomIdSet()); // Parse the config for atom ids. A combination atom matcher is a combination of (in the end) // simple atom matchers. So by adding all the atoms from the simple atom matchers // function adds all of the atoms. for (int i = 0; i < config.atom_matcher_size(); i++) { const AtomMatcher& matcher = config.atom_matcher(i); if (matcher.has_simple_atom_matcher()) { EXPECT_TRUE(matcher.simple_atom_matcher().has_atom_id()); resultList.insert(matcher.simple_atom_matcher().atom_id()); } } for (int i = 0; i < config.state_size(); i++) { const State& state = config.state(i); EXPECT_TRUE(state.has_atom_id()); resultList.insert(state.atom_id()); } return resultList; } void sortLogEventsByTimestamp(std::vector> *events) { std::sort(events->begin(), events->end(), [](const std::unique_ptr& a, const std::unique_ptr& b) { return a->GetElapsedTimestampNs() < b->GetElapsedTimestampNs(); }); } int64_t StringToId(const string& str) { return static_cast(std::hash()(str)); } sp createEventMatcherWizard( int tagId, int matcherIndex, const vector& fieldValueMatchers) { sp uidMap = new UidMap(); SimpleAtomMatcher atomMatcher; atomMatcher.set_atom_id(tagId); for (const FieldValueMatcher& fvm : fieldValueMatchers) { *atomMatcher.add_field_value_matcher() = fvm; } uint64_t matcherHash = 0x12345678; int64_t matcherId = 678; return new EventMatcherWizard( {new SimpleAtomMatchingTracker(matcherId, matcherHash, atomMatcher, uidMap)}); } StatsDimensionsValueParcel CreateAttributionUidDimensionsValueParcel(const int atomId, const int uid) { StatsDimensionsValueParcel root; root.field = atomId; root.valueType = STATS_DIMENSIONS_VALUE_TUPLE_TYPE; StatsDimensionsValueParcel attrNode; attrNode.field = 1; attrNode.valueType = STATS_DIMENSIONS_VALUE_TUPLE_TYPE; StatsDimensionsValueParcel posInAttrChain; posInAttrChain.field = 1; posInAttrChain.valueType = STATS_DIMENSIONS_VALUE_TUPLE_TYPE; StatsDimensionsValueParcel uidNode; uidNode.field = 1; uidNode.valueType = STATS_DIMENSIONS_VALUE_INT_TYPE; uidNode.intValue = uid; posInAttrChain.tupleValue.push_back(uidNode); attrNode.tupleValue.push_back(posInAttrChain); root.tupleValue.push_back(attrNode); return root; } void ValidateUidDimension(const DimensionsValue& value, int atomId, int uid) { EXPECT_EQ(value.field(), atomId); ASSERT_EQ(value.value_tuple().dimensions_value_size(), 1); EXPECT_EQ(value.value_tuple().dimensions_value(0).field(), 1); EXPECT_EQ(value.value_tuple().dimensions_value(0).value_int(), uid); } void ValidateWakelockAttributionUidAndTagDimension(const DimensionsValue& value, const int atomId, const int uid, const string& tag) { EXPECT_EQ(value.field(), atomId); ASSERT_EQ(value.value_tuple().dimensions_value_size(), 2); // Attribution field. EXPECT_EQ(value.value_tuple().dimensions_value(0).field(), 1); // Uid field. ASSERT_EQ(value.value_tuple().dimensions_value(0).value_tuple().dimensions_value_size(), 1); EXPECT_EQ(value.value_tuple().dimensions_value(0).value_tuple().dimensions_value(0).field(), 1); EXPECT_EQ(value.value_tuple().dimensions_value(0).value_tuple().dimensions_value(0).value_int(), uid); // Tag field. EXPECT_EQ(value.value_tuple().dimensions_value(1).field(), 3); EXPECT_EQ(value.value_tuple().dimensions_value(1).value_str(), tag); } void ValidateAttributionUidDimension(const DimensionsValue& value, int atomId, int uid) { EXPECT_EQ(value.field(), atomId); ASSERT_EQ(value.value_tuple().dimensions_value_size(), 1); // Attribution field. EXPECT_EQ(value.value_tuple().dimensions_value(0).field(), 1); // Uid only. EXPECT_EQ(value.value_tuple().dimensions_value(0) .value_tuple().dimensions_value_size(), 1); EXPECT_EQ(value.value_tuple().dimensions_value(0) .value_tuple().dimensions_value(0).field(), 1); EXPECT_EQ(value.value_tuple().dimensions_value(0) .value_tuple().dimensions_value(0).value_int(), uid); } void ValidateUidDimension(const DimensionsValue& value, int node_idx, int atomId, int uid) { EXPECT_EQ(value.field(), atomId); ASSERT_GT(value.value_tuple().dimensions_value_size(), node_idx); // Attribution field. EXPECT_EQ(value.value_tuple().dimensions_value(node_idx).field(), 1); EXPECT_EQ(value.value_tuple().dimensions_value(node_idx) .value_tuple().dimensions_value(0).field(), 1); EXPECT_EQ(value.value_tuple().dimensions_value(node_idx) .value_tuple().dimensions_value(0).value_int(), uid); } void ValidateAttributionUidAndTagDimension( const DimensionsValue& value, int node_idx, int atomId, int uid, const std::string& tag) { EXPECT_EQ(value.field(), atomId); ASSERT_GT(value.value_tuple().dimensions_value_size(), node_idx); // Attribution field. EXPECT_EQ(1, value.value_tuple().dimensions_value(node_idx).field()); // Uid only. EXPECT_EQ(2, value.value_tuple().dimensions_value(node_idx) .value_tuple().dimensions_value_size()); EXPECT_EQ(1, value.value_tuple().dimensions_value(node_idx) .value_tuple().dimensions_value(0).field()); EXPECT_EQ(uid, value.value_tuple().dimensions_value(node_idx) .value_tuple().dimensions_value(0).value_int()); EXPECT_EQ(2, value.value_tuple().dimensions_value(node_idx) .value_tuple().dimensions_value(1).field()); EXPECT_EQ(tag, value.value_tuple().dimensions_value(node_idx) .value_tuple().dimensions_value(1).value_str()); } void ValidateAttributionUidAndTagDimension( const DimensionsValue& value, int atomId, int uid, const std::string& tag) { EXPECT_EQ(value.field(), atomId); ASSERT_EQ(1, value.value_tuple().dimensions_value_size()); // Attribution field. EXPECT_EQ(1, value.value_tuple().dimensions_value(0).field()); // Uid only. EXPECT_EQ(value.value_tuple().dimensions_value(0) .value_tuple().dimensions_value_size(), 2); EXPECT_EQ(value.value_tuple().dimensions_value(0) .value_tuple().dimensions_value(0).field(), 1); EXPECT_EQ(value.value_tuple().dimensions_value(0) .value_tuple().dimensions_value(0).value_int(), uid); EXPECT_EQ(value.value_tuple().dimensions_value(0) .value_tuple().dimensions_value(1).field(), 2); EXPECT_EQ(value.value_tuple().dimensions_value(0) .value_tuple().dimensions_value(1).value_str(), tag); } void ValidateStateValue(const google::protobuf::RepeatedPtrField& stateValues, int atomId, int64_t value) { ASSERT_EQ(stateValues.size(), 1); ASSERT_EQ(stateValues[0].atom_id(), atomId); switch (stateValues[0].contents_case()) { case StateValue::ContentsCase::kValue: EXPECT_EQ(stateValues[0].value(), (int32_t)value); break; case StateValue::ContentsCase::kGroupId: EXPECT_EQ(stateValues[0].group_id(), value); break; default: FAIL() << "State value should have either a value or a group id"; } } void ValidateCountBucket(const CountBucketInfo& countBucket, int64_t startTimeNs, int64_t endTimeNs, int64_t count, int64_t conditionTrueNs) { EXPECT_EQ(countBucket.start_bucket_elapsed_nanos(), startTimeNs); EXPECT_EQ(countBucket.end_bucket_elapsed_nanos(), endTimeNs); EXPECT_EQ(countBucket.count(), count); EXPECT_EQ(countBucket.condition_true_nanos(), conditionTrueNs); } void ValidateDurationBucket(const DurationBucketInfo& bucket, int64_t startTimeNs, int64_t endTimeNs, int64_t durationNs, int64_t conditionTrueNs) { EXPECT_EQ(bucket.start_bucket_elapsed_nanos(), startTimeNs); EXPECT_EQ(bucket.end_bucket_elapsed_nanos(), endTimeNs); EXPECT_EQ(bucket.duration_nanos(), durationNs); EXPECT_EQ(bucket.condition_true_nanos(), conditionTrueNs); } void ValidateGaugeBucketTimes(const GaugeBucketInfo& gaugeBucket, int64_t startTimeNs, int64_t endTimeNs, vector eventTimesNs) { EXPECT_EQ(gaugeBucket.start_bucket_elapsed_nanos(), startTimeNs); EXPECT_EQ(gaugeBucket.end_bucket_elapsed_nanos(), endTimeNs); EXPECT_EQ(gaugeBucket.elapsed_timestamp_nanos_size(), eventTimesNs.size()); for (int i = 0; i < eventTimesNs.size(); i++) { EXPECT_EQ(gaugeBucket.elapsed_timestamp_nanos(i), eventTimesNs[i]); } } void ValidateValueBucket(const ValueBucketInfo& bucket, int64_t startTimeNs, int64_t endTimeNs, const vector& values, int64_t conditionTrueNs, int64_t conditionCorrectionNs) { EXPECT_EQ(bucket.start_bucket_elapsed_nanos(), startTimeNs); EXPECT_EQ(bucket.end_bucket_elapsed_nanos(), endTimeNs); ASSERT_EQ(bucket.values_size(), values.size()); for (int i = 0; i < values.size(); ++i) { if (bucket.values(i).has_value_double()) { EXPECT_EQ((int64_t)bucket.values(i).value_double(), values[i]); } else { EXPECT_EQ(bucket.values(i).value_long(), values[i]); } } if (conditionTrueNs > 0) { EXPECT_EQ(bucket.condition_true_nanos(), conditionTrueNs); if (conditionCorrectionNs > 0) { EXPECT_EQ(bucket.condition_correction_nanos(), conditionCorrectionNs); } } } void ValidateKllBucket(const KllBucketInfo& bucket, int64_t startTimeNs, int64_t endTimeNs, const vector sketchSizes, int64_t conditionTrueNs) { EXPECT_EQ(bucket.start_bucket_elapsed_nanos(), startTimeNs); EXPECT_EQ(bucket.end_bucket_elapsed_nanos(), endTimeNs); ASSERT_EQ(bucket.sketches_size(), sketchSizes.size()); for (int i = 0; i < sketchSizes.size(); ++i) { AggregatorStateProto aggProto; EXPECT_TRUE(aggProto.ParseFromString(bucket.sketches(i).kll_sketch())); EXPECT_EQ(aggProto.num_values(), sketchSizes[i]); } if (conditionTrueNs > 0) { EXPECT_EQ(bucket.condition_true_nanos(), conditionTrueNs); } } bool EqualsTo(const DimensionsValue& s1, const DimensionsValue& s2) { if (s1.field() != s2.field()) { return false; } if (s1.value_case() != s2.value_case()) { return false; } switch (s1.value_case()) { case DimensionsValue::ValueCase::kValueStr: return (s1.value_str() == s2.value_str()); case DimensionsValue::ValueCase::kValueInt: return s1.value_int() == s2.value_int(); case DimensionsValue::ValueCase::kValueLong: return s1.value_long() == s2.value_long(); case DimensionsValue::ValueCase::kValueBool: return s1.value_bool() == s2.value_bool(); case DimensionsValue::ValueCase::kValueFloat: return s1.value_float() == s2.value_float(); case DimensionsValue::ValueCase::kValueTuple: { if (s1.value_tuple().dimensions_value_size() != s2.value_tuple().dimensions_value_size()) { return false; } bool allMatched = true; for (int i = 0; allMatched && i < s1.value_tuple().dimensions_value_size(); ++i) { allMatched &= EqualsTo(s1.value_tuple().dimensions_value(i), s2.value_tuple().dimensions_value(i)); } return allMatched; } case DimensionsValue::ValueCase::VALUE_NOT_SET: default: return true; } } bool LessThan(const google::protobuf::RepeatedPtrField& s1, const google::protobuf::RepeatedPtrField& s2) { if (s1.size() != s2.size()) { return s1.size() < s2.size(); } for (int i = 0; i < s1.size(); i++) { const StateValue& state1 = s1[i]; const StateValue& state2 = s2[i]; if (state1.atom_id() != state2.atom_id()) { return state1.atom_id() < state2.atom_id(); } if (state1.value() != state2.value()) { return state1.value() < state2.value(); } if (state1.group_id() != state2.group_id()) { return state1.group_id() < state2.group_id(); } } return false; } bool LessThan(const DimensionsValue& s1, const DimensionsValue& s2) { if (s1.field() != s2.field()) { return s1.field() < s2.field(); } if (s1.value_case() != s2.value_case()) { return s1.value_case() < s2.value_case(); } switch (s1.value_case()) { case DimensionsValue::ValueCase::kValueStr: return s1.value_str() < s2.value_str(); case DimensionsValue::ValueCase::kValueInt: return s1.value_int() < s2.value_int(); case DimensionsValue::ValueCase::kValueLong: return s1.value_long() < s2.value_long(); case DimensionsValue::ValueCase::kValueBool: return (int)s1.value_bool() < (int)s2.value_bool(); case DimensionsValue::ValueCase::kValueFloat: return s1.value_float() < s2.value_float(); case DimensionsValue::ValueCase::kValueTuple: { if (s1.value_tuple().dimensions_value_size() != s2.value_tuple().dimensions_value_size()) { return s1.value_tuple().dimensions_value_size() < s2.value_tuple().dimensions_value_size(); } for (int i = 0; i < s1.value_tuple().dimensions_value_size(); ++i) { if (EqualsTo(s1.value_tuple().dimensions_value(i), s2.value_tuple().dimensions_value(i))) { continue; } else { return LessThan(s1.value_tuple().dimensions_value(i), s2.value_tuple().dimensions_value(i)); } } return false; } case DimensionsValue::ValueCase::VALUE_NOT_SET: default: return false; } } bool LessThan(const DimensionsPair& s1, const DimensionsPair& s2) { if (LessThan(s1.dimInWhat, s2.dimInWhat)) { return true; } else if (LessThan(s2.dimInWhat, s1.dimInWhat)) { return false; } return LessThan(s1.stateValues, s2.stateValues); } void backfillStringInDimension(const std::map& str_map, DimensionsValue* dimension) { if (dimension->has_value_str_hash()) { auto it = str_map.find((uint64_t)(dimension->value_str_hash())); if (it != str_map.end()) { dimension->clear_value_str_hash(); dimension->set_value_str(it->second); } else { ALOGE("Can not find the string hash: %llu", (unsigned long long)dimension->value_str_hash()); } } else if (dimension->has_value_tuple()) { auto value_tuple = dimension->mutable_value_tuple(); for (int i = 0; i < value_tuple->dimensions_value_size(); ++i) { backfillStringInDimension(str_map, value_tuple->mutable_dimensions_value(i)); } } } void backfillStringInReport(ConfigMetricsReport *config_report) { std::map str_map; for (const auto& str : config_report->strings()) { uint64_t hash = Hash64(str); if (str_map.find(hash) != str_map.end()) { ALOGE("String hash conflicts: %s %s", str.c_str(), str_map[hash].c_str()); } str_map[hash] = str; } for (int i = 0; i < config_report->metrics_size(); ++i) { auto metric_report = config_report->mutable_metrics(i); if (metric_report->has_count_metrics()) { backfillStringInDimension(str_map, metric_report->mutable_count_metrics()); } else if (metric_report->has_duration_metrics()) { backfillStringInDimension(str_map, metric_report->mutable_duration_metrics()); } else if (metric_report->has_gauge_metrics()) { backfillStringInDimension(str_map, metric_report->mutable_gauge_metrics()); } else if (metric_report->has_value_metrics()) { backfillStringInDimension(str_map, metric_report->mutable_value_metrics()); } else if (metric_report->has_kll_metrics()) { backfillStringInDimension(str_map, metric_report->mutable_kll_metrics()); } } // Backfill the package names. for (int i = 0 ; i < config_report->uid_map().snapshots_size(); ++i) { auto snapshot = config_report->mutable_uid_map()->mutable_snapshots(i); for (int j = 0 ; j < snapshot->package_info_size(); ++j) { auto package_info = snapshot->mutable_package_info(j); if (package_info->has_name_hash()) { auto it = str_map.find((uint64_t)(package_info->name_hash())); if (it != str_map.end()) { package_info->clear_name_hash(); package_info->set_name(it->second); } else { ALOGE("Can not find the string package name hash: %llu", (unsigned long long)package_info->name_hash()); } } } } // Backfill the app name in app changes. for (int i = 0 ; i < config_report->uid_map().changes_size(); ++i) { auto change = config_report->mutable_uid_map()->mutable_changes(i); if (change->has_app_hash()) { auto it = str_map.find((uint64_t)(change->app_hash())); if (it != str_map.end()) { change->clear_app_hash(); change->set_app(it->second); } else { ALOGE("Can not find the string change app name hash: %llu", (unsigned long long)change->app_hash()); } } } } void backfillStringInReport(ConfigMetricsReportList *config_report_list) { for (int i = 0; i < config_report_list->reports_size(); ++i) { backfillStringInReport(config_report_list->mutable_reports(i)); } } bool backfillDimensionPath(const DimensionsValue& path, const google::protobuf::RepeatedPtrField& leafValues, int* leafIndex, DimensionsValue* dimension) { dimension->set_field(path.field()); if (path.has_value_tuple()) { for (int i = 0; i < path.value_tuple().dimensions_value_size(); ++i) { if (!backfillDimensionPath(path.value_tuple().dimensions_value(i), leafValues, leafIndex, dimension->mutable_value_tuple()->add_dimensions_value())) { return false; } } } else { if (*leafIndex < 0 || *leafIndex >= leafValues.size()) { return false; } dimension->MergeFrom(leafValues.Get(*leafIndex)); (*leafIndex)++; } return true; } bool backfillDimensionPath(const DimensionsValue& path, const google::protobuf::RepeatedPtrField& leafValues, DimensionsValue* dimension) { int leafIndex = 0; return backfillDimensionPath(path, leafValues, &leafIndex, dimension); } void backfillDimensionPath(StatsLogReport* report) { if (report->has_dimensions_path_in_what()) { auto whatPath = report->dimensions_path_in_what(); if (report->has_count_metrics()) { backfillDimensionPath(whatPath, report->mutable_count_metrics()); } else if (report->has_duration_metrics()) { backfillDimensionPath(whatPath, report->mutable_duration_metrics()); } else if (report->has_gauge_metrics()) { backfillDimensionPath(whatPath, report->mutable_gauge_metrics()); } else if (report->has_value_metrics()) { backfillDimensionPath(whatPath, report->mutable_value_metrics()); } else if (report->has_kll_metrics()) { backfillDimensionPath(whatPath, report->mutable_kll_metrics()); } report->clear_dimensions_path_in_what(); } } void backfillDimensionPath(ConfigMetricsReport* config_report) { for (int i = 0; i < config_report->metrics_size(); ++i) { backfillDimensionPath(config_report->mutable_metrics(i)); } } void backfillDimensionPath(ConfigMetricsReportList* config_report_list) { for (int i = 0; i < config_report_list->reports_size(); ++i) { backfillDimensionPath(config_report_list->mutable_reports(i)); } } void backfillStartEndTimestamp(StatsLogReport *report) { const int64_t timeBaseNs = report->time_base_elapsed_nano_seconds(); const int64_t bucketSizeNs = report->bucket_size_nano_seconds(); if (report->has_count_metrics()) { backfillStartEndTimestampForMetrics( timeBaseNs, bucketSizeNs, report->mutable_count_metrics()); } else if (report->has_duration_metrics()) { backfillStartEndTimestampForMetrics( timeBaseNs, bucketSizeNs, report->mutable_duration_metrics()); } else if (report->has_gauge_metrics()) { backfillStartEndTimestampForMetrics( timeBaseNs, bucketSizeNs, report->mutable_gauge_metrics()); if (report->gauge_metrics().skipped_size() > 0) { backfillStartEndTimestampForSkippedBuckets( timeBaseNs, report->mutable_gauge_metrics()); } } else if (report->has_value_metrics()) { backfillStartEndTimestampForMetrics( timeBaseNs, bucketSizeNs, report->mutable_value_metrics()); if (report->value_metrics().skipped_size() > 0) { backfillStartEndTimestampForSkippedBuckets( timeBaseNs, report->mutable_value_metrics()); } } else if (report->has_kll_metrics()) { backfillStartEndTimestampForMetrics(timeBaseNs, bucketSizeNs, report->mutable_kll_metrics()); if (report->kll_metrics().skipped_size() > 0) { backfillStartEndTimestampForSkippedBuckets(timeBaseNs, report->mutable_kll_metrics()); } } } void backfillStartEndTimestamp(ConfigMetricsReport *config_report) { for (int j = 0; j < config_report->metrics_size(); ++j) { backfillStartEndTimestamp(config_report->mutable_metrics(j)); } } void backfillStartEndTimestamp(ConfigMetricsReportList *config_report_list) { for (int i = 0; i < config_report_list->reports_size(); ++i) { backfillStartEndTimestamp(config_report_list->mutable_reports(i)); } } void backfillAggregatedAtoms(ConfigMetricsReportList* config_report_list) { for (int i = 0; i < config_report_list->reports_size(); ++i) { backfillAggregatedAtoms(config_report_list->mutable_reports(i)); } } void backfillAggregatedAtoms(ConfigMetricsReport* config_report) { for (int i = 0; i < config_report->metrics_size(); ++i) { backfillAggregatedAtoms(config_report->mutable_metrics(i)); } } void backfillAggregatedAtoms(StatsLogReport* report) { if (report->has_event_metrics()) { backfillAggregatedAtomsInEventMetric(report->mutable_event_metrics()); } if (report->has_gauge_metrics()) { backfillAggregatedAtomsInGaugeMetric(report->mutable_gauge_metrics()); } } void backfillAggregatedAtomsInEventMetric(StatsLogReport::EventMetricDataWrapper* wrapper) { std::vector metricData; for (int i = 0; i < wrapper->data_size(); ++i) { AggregatedAtomInfo* atomInfo = wrapper->mutable_data(i)->mutable_aggregated_atom_info(); for (int j = 0; j < atomInfo->elapsed_timestamp_nanos_size(); j++) { EventMetricData data; *(data.mutable_atom()) = atomInfo->atom(); data.set_elapsed_timestamp_nanos(atomInfo->elapsed_timestamp_nanos(j)); metricData.push_back(data); } } if (metricData.size() == 0) { return; } sort(metricData.begin(), metricData.end(), [](const EventMetricData& lhs, const EventMetricData& rhs) { return lhs.elapsed_timestamp_nanos() < rhs.elapsed_timestamp_nanos(); }); wrapper->clear_data(); for (int i = 0; i < metricData.size(); ++i) { *(wrapper->add_data()) = metricData[i]; } } void backfillAggregatedAtomsInGaugeMetric(StatsLogReport::GaugeMetricDataWrapper* wrapper) { for (int i = 0; i < wrapper->data_size(); ++i) { for (int j = 0; j < wrapper->data(i).bucket_info_size(); ++j) { GaugeBucketInfo* bucketInfo = wrapper->mutable_data(i)->mutable_bucket_info(j); vector> atomData = unnestGaugeAtomData(*bucketInfo); if (atomData.size() == 0) { return; } bucketInfo->clear_aggregated_atom_info(); ASSERT_EQ(bucketInfo->atom_size(), 0); ASSERT_EQ(bucketInfo->elapsed_timestamp_nanos_size(), 0); for (int k = 0; k < atomData.size(); ++k) { *(bucketInfo->add_atom()) = atomData[k].first; bucketInfo->add_elapsed_timestamp_nanos(atomData[k].second); } } } } vector> unnestGaugeAtomData(const GaugeBucketInfo& bucketInfo) { vector> atomData; for (int k = 0; k < bucketInfo.aggregated_atom_info_size(); ++k) { const AggregatedAtomInfo& atomInfo = bucketInfo.aggregated_atom_info(k); for (int l = 0; l < atomInfo.elapsed_timestamp_nanos_size(); ++l) { atomData.push_back(make_pair(atomInfo.atom(), atomInfo.elapsed_timestamp_nanos(l))); } } sort(atomData.begin(), atomData.end(), [](const pair& lhs, const pair& rhs) { return lhs.second < rhs.second; }); return atomData; } void sortReportsByElapsedTime(ConfigMetricsReportList* configReportList) { RepeatedPtrField* reports = configReportList->mutable_reports(); sort(reports->pointer_begin(), reports->pointer_end(), [](const ConfigMetricsReport* lhs, const ConfigMetricsReport* rhs) { return lhs->current_report_elapsed_nanos() < rhs->current_report_elapsed_nanos(); }); } Status FakeSubsystemSleepCallback::onPullAtom(int atomTag, const shared_ptr& resultReceiver) { // Convert stats_events into StatsEventParcels. std::vector parcels; for (int i = 1; i < 3; i++) { AStatsEvent* event = AStatsEvent_obtain(); AStatsEvent_setAtomId(event, atomTag); std::string subsystemName = "subsystem_name_"; subsystemName = subsystemName + std::to_string(i); AStatsEvent_writeString(event, subsystemName.c_str()); AStatsEvent_writeString(event, "subsystem_subname foo"); AStatsEvent_writeInt64(event, /*count= */ i); AStatsEvent_writeInt64(event, /*time_millis= */ pullNum * pullNum * 100 + i); AStatsEvent_build(event); size_t size; uint8_t* buffer = AStatsEvent_getBuffer(event, &size); StatsEventParcel p; // vector.assign() creates a copy, but this is inevitable unless // stats_event.h/c uses a vector as opposed to a buffer. p.buffer.assign(buffer, buffer + size); parcels.push_back(std::move(p)); AStatsEvent_release(event); } pullNum++; resultReceiver->pullFinished(atomTag, /*success=*/true, parcels); return Status::ok(); } void writeFlag(const string& flagName, const string& flagValue) { SetProperty(StringPrintf("persist.device_config.%s.%s", STATSD_NATIVE_NAMESPACE.c_str(), flagName.c_str()), flagValue); } void writeBootFlag(const string& flagName, const string& flagValue) { SetProperty(StringPrintf("persist.device_config.%s.%s", STATSD_NATIVE_BOOT_NAMESPACE.c_str(), flagName.c_str()), flagValue); } PackageInfoSnapshot getPackageInfoSnapshot(const sp uidMap) { ProtoOutputStream protoOutputStream; uidMap->writeUidMapSnapshot(/* timestamp */ 1, {/* includeVersionStrings */ true, /* includeInstaller */ true, /* certificateHashSize */ UINT8_MAX, /* omitSystemUids */ false}, /* interestingUids */ {}, /* installerIndices */ nullptr, /* str_set */ nullptr, &protoOutputStream); PackageInfoSnapshot packageInfoSnapshot; outputStreamToProto(&protoOutputStream, &packageInfoSnapshot); return packageInfoSnapshot; } PackageInfo buildPackageInfo(const string& name, const int32_t uid, const int64_t version, const string& versionString, const optional installer, const vector& certHash, const bool deleted, const bool hashStrings, const optional installerIndex) { PackageInfo packageInfo; packageInfo.set_version(version); packageInfo.set_uid(uid); packageInfo.set_deleted(deleted); if (!certHash.empty()) { packageInfo.set_truncated_certificate_hash(certHash.data(), certHash.size()); } if (hashStrings) { packageInfo.set_name_hash(Hash64(name)); packageInfo.set_version_string_hash(Hash64(versionString)); } else { packageInfo.set_name(name); packageInfo.set_version_string(versionString); } if (installer) { if (installerIndex) { packageInfo.set_installer_index(*installerIndex); } else if (hashStrings) { packageInfo.set_installer_hash(Hash64(*installer)); } else { packageInfo.set_installer(*installer); } } return packageInfo; } vector buildPackageInfos( const vector& names, const vector& uids, const vector& versions, const vector& versionStrings, const vector& installers, const vector>& certHashes, const vector& deleted, const vector& installerIndices, const bool hashStrings) { vector packageInfos; for (int i = 0; i < uids.size(); i++) { const optional installerIndex = installerIndices.empty() ? nullopt : optional(installerIndices[i]); const optional installer = installers.empty() ? nullopt : optional(installers[i]); vector certHash; if (!certHashes.empty()) { certHash = certHashes[i]; } packageInfos.emplace_back(buildPackageInfo(names[i], uids[i], versions[i], versionStrings[i], installer, certHash, deleted[i], hashStrings, installerIndex)); } return packageInfos; } ApplicationInfo createApplicationInfo(const int32_t uid, const int64_t version, const string& versionString, const string& package) { ApplicationInfo info; info.set_uid(uid); info.set_version(version); info.set_version_string(versionString); info.set_package_name(package); return info; } StatsdStatsReport_PulledAtomStats getPulledAtomStats(int32_t atom_id) { StatsdStatsReport statsReport = getStatsdStatsReport(); StatsdStatsReport_PulledAtomStats pulledAtomStats; for (size_t i = 0; i < statsReport.pulled_atom_stats_size(); i++) { if (statsReport.pulled_atom_stats(i).atom_id() == atom_id) { return statsReport.pulled_atom_stats(i); } } return pulledAtomStats; } void createStatsEvent(AStatsEvent* statsEvent, uint8_t typeId, uint32_t atomId) { AStatsEvent_setAtomId(statsEvent, atomId); fillStatsEventWithSampleValue(statsEvent, typeId); } void fillStatsEventWithSampleValue(AStatsEvent* statsEvent, uint8_t typeId) { int int32Array[2] = {3, 6}; uint32_t uids[] = {1001, 1002}; const char* tags[] = {"tag1", "tag2"}; switch (typeId) { case INT32_TYPE: AStatsEvent_writeInt32(statsEvent, 10); break; case INT64_TYPE: AStatsEvent_writeInt64(statsEvent, 1000L); break; case STRING_TYPE: AStatsEvent_writeString(statsEvent, "test"); break; case LIST_TYPE: if (__builtin_available(android __ANDROID_API_T__, *)) { /* CAUTION: when using this function with LIST_TYPE, wrap the code in a __builtin_available or __INTRODUCED_IN w/ T. */ AStatsEvent_writeInt32Array(statsEvent, int32Array, 2); } else { ADD_FAILURE() << "fillStatsEventWithSampleValue() w/ typeId LIST_TYPE should only " "be used on Android T or above."; } break; case FLOAT_TYPE: AStatsEvent_writeFloat(statsEvent, 1.3f); break; case BOOL_TYPE: AStatsEvent_writeBool(statsEvent, 1); break; case BYTE_ARRAY_TYPE: AStatsEvent_writeByteArray(statsEvent, (uint8_t*)"test", strlen("test")); break; case ATTRIBUTION_CHAIN_TYPE: AStatsEvent_writeAttributionChain(statsEvent, uids, tags, 2); break; default: break; } } StatsdStatsReport getStatsdStatsReport(bool resetStats) { StatsdStats& stats = StatsdStats::getInstance(); return getStatsdStatsReport(stats, resetStats); } StatsdStatsReport getStatsdStatsReport(StatsdStats& stats, bool resetStats) { vector statsBuffer; stats.dumpStats(&statsBuffer, resetStats); StatsdStatsReport statsReport; EXPECT_TRUE(statsReport.ParseFromArray(statsBuffer.data(), statsBuffer.size())); return statsReport; } StatsdConfig buildGoodConfig(int configId) { StatsdConfig config; config.set_id(configId); AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher(); *config.add_atom_matcher() = screenOnMatcher; *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); AtomMatcher* eventMatcher = config.add_atom_matcher(); eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF")); AtomMatcher_Combination* combination = eventMatcher->mutable_combination(); combination->set_operation(LogicalOperation::OR); combination->add_matcher(screenOnMatcher.id()); combination->add_matcher(StringToId("ScreenTurnedOff")); CountMetric* countMetric = config.add_count_metric(); *countMetric = createCountMetric("Count", screenOnMatcher.id() /* what */, nullopt /* condition */, {} /* states */); countMetric->mutable_dimensions_in_what()->set_field(SCREEN_STATE_ATOM_ID); countMetric->mutable_dimensions_in_what()->add_child()->set_field(1); config.add_no_report_metric(StringToId("Count")); *config.add_predicate() = CreateScreenIsOnPredicate(); *config.add_duration_metric() = createDurationMetric("Duration", StringToId("ScreenIsOn") /* what */, nullopt /* condition */, {} /* states */); *config.add_gauge_metric() = createGaugeMetric( "Gauge", screenOnMatcher.id() /* what */, GaugeMetric_SamplingType_FIRST_N_SAMPLES, nullopt /* condition */, nullopt /* triggerEvent */); *config.add_value_metric() = createValueMetric("Value", screenOnMatcher /* what */, 2 /* valueField */, nullopt /* condition */, {} /* states */); *config.add_kll_metric() = createKllMetric("Kll", screenOnMatcher /* what */, 2 /* kllField */, nullopt /* condition */); return config; } StatsdConfig buildGoodConfig(int configId, int alertId) { StatsdConfig config = buildGoodConfig(configId); auto alert = config.add_alert(); alert->set_id(alertId); alert->set_metric_id(StringToId("Count")); alert->set_num_buckets(10); alert->set_refractory_period_secs(100); alert->set_trigger_if_sum_gt(100); return config; } sp makeMockConfigMetadataProvider(bool enabled) { sp metadataProvider = new StrictMock(); EXPECT_CALL(*metadataProvider, useV2SoftMemoryCalculation()).Times(AnyNumber()); EXPECT_CALL(*metadataProvider, useV2SoftMemoryCalculation()).WillRepeatedly(Return(enabled)); return nullptr; } SocketLossInfo createSocketLossInfo(int32_t uid, int32_t atomId) { SocketLossInfo lossInfo; lossInfo.uid = uid; lossInfo.errors.push_back(-11); lossInfo.atomIds.push_back(atomId); lossInfo.counts.push_back(1); return lossInfo; } std::unique_ptr createSocketLossInfoLogEvent(int32_t uid, int32_t lossAtomId) { const SocketLossInfo lossInfo = createSocketLossInfo(uid, lossAtomId); AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::STATS_SOCKET_LOSS_REPORTED); AStatsEvent_writeInt32(statsEvent, lossInfo.uid); AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_IS_UID, true); AStatsEvent_writeInt64(statsEvent, lossInfo.firstLossTsNanos); AStatsEvent_writeInt64(statsEvent, lossInfo.lastLossTsNanos); AStatsEvent_writeInt32(statsEvent, lossInfo.overflowCounter); AStatsEvent_writeInt32Array(statsEvent, lossInfo.errors.data(), lossInfo.errors.size()); AStatsEvent_writeInt32Array(statsEvent, lossInfo.atomIds.data(), lossInfo.atomIds.size()); AStatsEvent_writeInt32Array(statsEvent, lossInfo.counts.data(), lossInfo.counts.size()); std::unique_ptr logEvent = std::make_unique(uid /* uid */, 0 /* pid */); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } } // namespace statsd } // namespace os } // namespace android