// 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 "matchers/SimpleAtomMatchingTracker.h" #include "stats_annotations.h" #include "stats_event.h" using aidl::android::util::StatsEventParcel; using std::shared_ptr; namespace android { namespace os { namespace statsd { 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 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); } 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(1111123); 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(33333333333333); 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; } 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 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) { 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()); metric.mutable_value_field()->add_child()->set_field(valueField); if (condition) { metric.set_condition(condition.value()); } for (const int64_t state : states) { metric.add_slice_by_state(state); } 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()); } void parseStatsEventToLogEvent(AStatsEvent* statsEvent, LogEvent* logEvent) { AStatsEvent_build(statsEvent); size_t size; uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); logEvent->parseBuffer(buf, size); AStatsEvent_release(statsEvent); } void CreateTwoValueLogEvent(LogEvent* logEvent, 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); 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; } shared_ptr makeUidLogEvent(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, 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 makeAttributionLogEvent(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); shared_ptr logEvent = std::make_shared(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); return logEvent; } sp makeMockUidMapForOneHost(int hostUid, const vector& isolatedUids) { sp uidMap = new NaggyMock(); EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(ReturnArg<0>()); 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, ANNOTATION_ID_EXCLUSIVE_STATE, true); AStatsEvent_addBoolAnnotation(statsEvent, 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, ANNOTATION_ID_EXCLUSIVE_STATE, true); AStatsEvent_addBoolAnnotation(statsEvent, 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, ANNOTATION_ID_EXCLUSIVE_STATE, true); AStatsEvent_addBoolAnnotation(statsEvent, 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) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::PLUGGED_STATE_CHANGED); 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; } 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); } 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, ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, true); AStatsEvent_writeInt32(statsEvent, android::os::WakeLockLevelEnum::PARTIAL_WAKE_LOCK); AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_PRIMARY_FIELD, true); AStatsEvent_writeString(statsEvent, wakelockName.c_str()); AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_PRIMARY_FIELD, true); AStatsEvent_writeInt32(statsEvent, state); AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_EXCLUSIVE_STATE, true); AStatsEvent_addBoolAnnotation(statsEvent, 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 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, "pkg_name"); AStatsEvent_writeString(statsEvent, "class_name"); 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, ActivityForegroundStateChanged::BACKGROUND); } std::unique_ptr CreateMoveToForegroundEvent(uint64_t timestampNs, const int uid) { return CreateActivityForegroundStateChangedEvent(timestampNs, uid, 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, ANNOTATION_ID_IS_UID, true); AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_PRIMARY_FIELD, true); AStatsEvent_writeInt32(statsEvent, state); AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_EXCLUSIVE_STATE, true); AStatsEvent_addBoolAnnotation(statsEvent, 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, ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, true); AStatsEvent_writeInt32(statsEvent, state); AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_EXCLUSIVE_STATE, true); AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_STATE_NESTED, true); if (state == util::BLE_SCAN_STATE_CHANGED__STATE__RESET) { AStatsEvent_addInt32Annotation(statsEvent, ANNOTATION_ID_TRIGGER_STATE_RESET, util::BLE_SCAN_STATE_CHANGED__STATE__OFF); } AStatsEvent_writeBool(statsEvent, filtered); // filtered AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_PRIMARY_FIELD, true); AStatsEvent_writeBool(statsEvent, firstMatch); // first match AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_PRIMARY_FIELD, true); AStatsEvent_writeBool(statsEvent, opportunistic); // opportunistic AStatsEvent_addBoolAnnotation(statsEvent, 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, ANNOTATION_ID_IS_UID, true); AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_PRIMARY_FIELD, true); AStatsEvent_writeString(statsEvent, packageName.c_str()); AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_PRIMARY_FIELD, true); AStatsEvent_writeBool(statsEvent, usingAlertWindow); AStatsEvent_writeInt32(statsEvent, state); AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_EXCLUSIVE_STATE, true); AStatsEvent_addBoolAnnotation(statsEvent, 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; } 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) { sp pullerManager = new StatsPullerManager(); 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;}); processor->OnConfigUpdated(currentTimeNs, key, config); return processor; } 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, matcherIndex, 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) { EXPECT_EQ(countBucket.start_bucket_elapsed_nanos(), startTimeNs); EXPECT_EQ(countBucket.end_bucket_elapsed_nanos(), endTimeNs); EXPECT_EQ(countBucket.count(), count); } void ValidateDurationBucket(const DurationBucketInfo& bucket, int64_t startTimeNs, int64_t endTimeNs, int64_t durationNs) { EXPECT_EQ(bucket.start_bucket_elapsed_nanos(), startTimeNs); EXPECT_EQ(bucket.end_bucket_elapsed_nanos(), endTimeNs); EXPECT_EQ(bucket.duration_nanos(), durationNs); } 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) { 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); } } 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()); } } // 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() || report->has_dimensions_path_in_condition()) { auto whatPath = report->dimensions_path_in_what(); auto conditionPath = report->dimensions_path_in_condition(); if (report->has_count_metrics()) { backfillDimensionPath(whatPath, conditionPath, report->mutable_count_metrics()); } else if (report->has_duration_metrics()) { backfillDimensionPath(whatPath, conditionPath, report->mutable_duration_metrics()); } else if (report->has_gauge_metrics()) { backfillDimensionPath(whatPath, conditionPath, report->mutable_gauge_metrics()); } else if (report->has_value_metrics()) { backfillDimensionPath(whatPath, conditionPath, report->mutable_value_metrics()); } report->clear_dimensions_path_in_what(); report->clear_dimensions_path_in_condition(); } } 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()); } } } 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)); } } 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(); } } // namespace statsd } // namespace os } // namespace android