diff options
Diffstat (limited to 'cmds/statsd/src')
23 files changed, 260 insertions, 88 deletions
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h index ffd83ba978f4..7090bd46635d 100644 --- a/cmds/statsd/src/StatsLogProcessor.h +++ b/cmds/statsd/src/StatsLogProcessor.h @@ -307,9 +307,6 @@ private: FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation); FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition); FRIEND_TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents); - FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents); - FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm); - FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation); FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket); FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets); @@ -328,6 +325,7 @@ private: FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithSameDeactivation); FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoMetricsTwoDeactivations); + FRIEND_TEST(CountMetricE2eTest, TestInitialConditionChanges); FRIEND_TEST(CountMetricE2eTest, TestSlicedState); FRIEND_TEST(CountMetricE2eTest, TestSlicedStateWithMap); FRIEND_TEST(CountMetricE2eTest, TestMultipleSlicedStates); @@ -345,6 +343,10 @@ private: FRIEND_TEST(DurationMetricE2eTest, TestSlicedStatePrimaryFieldsNotSubsetDimInWhat); FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSubset); + FRIEND_TEST(ValueMetricE2eTest, TestInitialConditionChanges); + FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents); + FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm); + FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation); FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState); FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions); FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions); diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index a65f5f792daa..4ffa040fafd4 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -826,7 +826,7 @@ status_t StatsService::cmd_print_pulled_metrics(int out, const Vector<String8>& uids.push_back(AID_SYSTEM); } vector<shared_ptr<LogEvent>> stats; - if (mPullerManager->Pull(s, uids, &stats)) { + if (mPullerManager->Pull(s, uids, getElapsedRealtimeNs(), &stats)) { for (const auto& it : stats) { dprintf(out, "Pull from %d: %s\n", s, it->ToString().c_str()); } diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 4db0f91ca871..12158b318676 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -440,6 +440,7 @@ message Atom { 273 [(module) = "permissioncontroller"]; EvsUsageStatsReported evs_usage_stats_reported = 274 [(module) = "evs"]; AudioPowerUsageDataReported audio_power_usage_data_reported = 275; + TvTunerStateChanged tv_tuner_state_changed = 276 [(module) = "framework"]; SdkExtensionStatus sdk_extension_status = 354; // StatsdStats tracks platform atoms with ids upto 500. @@ -447,7 +448,7 @@ message Atom { } // Pulled events will start at field 10000. - // Next: 10080 + // Next: 10084 oneof pulled { WifiBytesTransfer wifi_bytes_transfer = 10000 [(module) = "framework"]; WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001 [(module) = "framework"]; @@ -538,6 +539,10 @@ message Atom { SimSlotState sim_slot_state = 10078 [(module) = "telephony"]; SupportedRadioAccessFamily supported_radio_access_family = 10079 [(module) = "telephony"]; SettingSnapshot setting_snapshot = 10080 [(module) = "framework"]; + DisplayWakeReason display_wake_reason = 10081 [(module) = "framework"]; + DataUsageBytesTransfer data_usage_bytes_transfer = 10082 [(module) = "framework"]; + BytesTransferByTagAndMetered bytes_transfer_by_tag_and_metered = + 10083 [(module) = "framework"]; } // DO NOT USE field numbers above 100,000 in AOSP. @@ -4939,6 +4944,60 @@ message MobileBytesTransferByFgBg { } /** + * Used for pull network statistics via mobile|wifi networks, and sliced by interesting dimensions. + * Note that the data is expected to be sliced into more dimensions in future. In other words, + * the caller must not assume any row of data is one full report when filtering with a set of + * matching conditions, because future data may represent with multiple rows what is currently + * represented by one. + * To avoid being broken by future slicing, callers must take care to aggregate rows even if they + * query all the existing columns. + * + * Pulled from: + * StatsPullAtomService (using NetworkStatsService to get NetworkStats) + */ +message DataUsageBytesTransfer { + // State of this record. Should be NetworkStats#SET_DEFAULT or NetworkStats#SET_FOREGROUND to + // indicate the foreground state, or NetworkStats#SET_ALL to indicate the record is for all + // states combined, not including debug states. See NetworkStats#SET_*. + optional int32 state = 1; + + optional int64 rx_bytes = 2; + + optional int64 rx_packets = 3; + + optional int64 tx_bytes = 4; + + optional int64 tx_packets = 5; + + // Radio Access Technology (RAT) type of this record, should be one of + // TelephonyManager#NETWORK_TYPE_* constants, or NetworkTemplate#NETWORK_TYPE_ALL to indicate + // the record is for all rat types combined. + optional int32 rat_type = 6; + + // Mcc/Mnc read from sim if the record is for a specific subscription, null indicates the + // record is combined across subscriptions. + optional string sim_mcc = 7; + optional string sim_mnc = 8; + + // Allows mobile virtual network operators (MVNOs) to be identified with individual IDs. + // See TelephonyManager#getSimCarrierId. + optional int32 carrier_id = 9; + + // Enumeration of opportunistic states with an additional ALL state indicates the record is + // combined regardless of the boolean value in its field. + enum DataSubscriptionState { + UNKNOWN = 0; // For server side backward compatibility. + ALL = 1; + OPPORTUNISTIC = 2; + NOT_OPPORTUNISTIC = 3; + } + // Mark whether the subscription is an opportunistic data subscription, and ALL indicates the + // record is combined across opportunistic data subscriptions. + // See {@link SubscriptionManager#setOpportunistic}. + optional DataSubscriptionState opportunistic_data_sub = 10; +} + +/** * Pulls bytes transferred via bluetooth. It is pulled from Bluetooth controller. * * Pulled from: @@ -5981,6 +6040,12 @@ message PackageNotificationChannelPreferences { optional int32 user_locked_fields = 6; // Indicates if the channel was deleted by the app. optional bool is_deleted = 7; + // Indicates if the channel was marked as a conversation by the app. + optional bool is_conversation = 8; + // Indicates if the channel is a conversation that was demoted by the user. + optional bool is_demoted_conversation = 9; + // Indicates if the channel is a conversation that was marked as important by the user. + optional bool is_important_conversation = 10; } /** @@ -9120,6 +9185,28 @@ message SdkExtensionStatus { } /** + * Logs when a tune occurs through device's Frontend. + * This is atom ID 276. + * + * Logged from: + * frameworks/base/media/java/android/media/tv/tuner/Tuner.java + */ +message TvTunerStateChanged { + enum State { + UNKNOWN = 0; + TUNING = 1; // Signal is tuned + LOCKED = 2; // the signal is locked + NOT_LOCKED = 3; // the signal isn’t locked. + SIGNAL_LOST = 4; // the signal was locked, but is lost now. + SCANNING = 5; // the signal is scanned + SCAN_STOPPED = 6; // the scan is stopped. + } + // The uid of the application that sent this custom atom. + optional int32 uid = 1 [(is_uid) = true]; + // new state + optional State state = 2; +} +/** * Logs when an app is frozen or unfrozen. * * Logged from: @@ -9461,9 +9548,6 @@ message TvSettingsUIInteracted { /** The ID of the entry that the users actioned on */ optional android.app.tvsettings.ItemId item_id = 2; - - /** Additional information (e.g., navigation direction on page focused) */ - optional string additional_info = 3; } /** @@ -9589,6 +9673,9 @@ message UserLifecycleEventOccurred { SWITCH_USER = 1; // Indicates that this is a user switch event START_USER = 2; // Indicates that this is a user start event CREATE_USER = 3; // Indicates that this is a user create event + USER_RUNNING_LOCKED = 4; // Indicates that user is running in locked state + UNLOCKING_USER = 5; // Indicates that this is a user unlocking event + UNLOCKED_USER = 6; // Indicates that this is a user unlocked event } optional Event event = 3; @@ -9635,6 +9722,17 @@ message AccessibilityServiceReported { optional android.stats.accessibility.ServiceStatus service_status = 2; } +message DisplayWakeReason { + // Wake_up_reason code + // If LOWORD(wake_up_reason) = 0 + // reference to HIWORD(wake_up_reason) PowerManager.WAKE_REASON_XXX + // else reference wake_up_reason to + // frameworks/base/services/core/java/com/android/server/power/Notifier.java#DispWakeupReason + optional int32 wake_up_reason = 1; + // Count of wake up by reason + optional int32 wake_times = 2; +} + /** * Logs app usage events. */ @@ -9747,3 +9845,25 @@ message AudioPowerUsageDataReported { } optional AudioType type = 4; } + +/** + * Pulls bytes transferred over WiFi and mobile networks sliced by uid, is_metered, and tag. + * + * Pulled from: + * StatsPullAtomService, which uses NetworkStatsService to query NetworkStats. + */ +message BytesTransferByTagAndMetered { + optional int32 uid = 1 [(is_uid) = true]; + + optional bool is_metered = 2; + + optional int32 tag = 3; + + optional int64 rx_bytes = 4; + + optional int64 rx_packets = 5; + + optional int64 tx_bytes = 6; + + optional int64 tx_packets = 7; +} diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp index 829a60345ba7..9df4d1f8ce24 100644 --- a/cmds/statsd/src/external/StatsPuller.cpp +++ b/cmds/statsd/src/external/StatsPuller.cpp @@ -38,14 +38,16 @@ StatsPuller::StatsPuller(const int tagId, const int64_t coolDownNs, const int64_ mPullTimeoutNs(pullTimeoutNs), mCoolDownNs(coolDownNs), mAdditiveFields(additiveFields), - mLastPullTimeNs(0) { + mLastPullTimeNs(0), + mLastEventTimeNs(0) { } -bool StatsPuller::Pull(std::vector<std::shared_ptr<LogEvent>>* data) { +bool StatsPuller::Pull(const int64_t eventTimeNs, std::vector<std::shared_ptr<LogEvent>>* data) { lock_guard<std::mutex> lock(mLock); int64_t elapsedTimeNs = getElapsedRealtimeNs(); StatsdStats::getInstance().notePull(mTagId); - const bool shouldUseCache = elapsedTimeNs - mLastPullTimeNs < mCoolDownNs; + const bool shouldUseCache = + (mLastEventTimeNs == eventTimeNs) || (elapsedTimeNs - mLastPullTimeNs < mCoolDownNs); if (shouldUseCache) { if (mHasGoodData) { (*data) = mCachedData; @@ -54,13 +56,13 @@ bool StatsPuller::Pull(std::vector<std::shared_ptr<LogEvent>>* data) { } return mHasGoodData; } - if (mLastPullTimeNs > 0) { StatsdStats::getInstance().updateMinPullIntervalSec( mTagId, (elapsedTimeNs - mLastPullTimeNs) / NS_PER_SEC); } mCachedData.clear(); mLastPullTimeNs = elapsedTimeNs; + mLastEventTimeNs = eventTimeNs; mHasGoodData = PullInternal(&mCachedData); if (!mHasGoodData) { return mHasGoodData; @@ -70,7 +72,7 @@ bool StatsPuller::Pull(std::vector<std::shared_ptr<LogEvent>>* data) { const bool pullTimeOut = pullDurationNs > mPullTimeoutNs; if (pullTimeOut) { // Something went wrong. Discard the data. - clearCacheLocked(); + mCachedData.clear(); mHasGoodData = false; StatsdStats::getInstance().notePullTimeout(mTagId); ALOGW("Pull for atom %d exceeds timeout %lld nano seconds.", mTagId, @@ -104,6 +106,7 @@ int StatsPuller::clearCacheLocked() { int ret = mCachedData.size(); mCachedData.clear(); mLastPullTimeNs = 0; + mLastEventTimeNs = 0; return ret; } diff --git a/cmds/statsd/src/external/StatsPuller.h b/cmds/statsd/src/external/StatsPuller.h index fee571c52a5f..470d15e6fbd1 100644 --- a/cmds/statsd/src/external/StatsPuller.h +++ b/cmds/statsd/src/external/StatsPuller.h @@ -51,7 +51,7 @@ public: // 2) pull takes longer than mPullTimeoutNs (intrinsic to puller) // If a metric wants to make any change to the data, like timestamps, it // should make a copy as this data may be shared with multiple metrics. - bool Pull(std::vector<std::shared_ptr<LogEvent>>* data); + bool Pull(const int64_t eventTimeNs, std::vector<std::shared_ptr<LogEvent>>* data); // Clear cache immediately int ForceClearCache(); @@ -94,6 +94,11 @@ private: int64_t mLastPullTimeNs; + // All pulls happen due to an event (app upgrade, bucket boundary, condition change, etc). + // If multiple pulls need to be done at the same event time, we will always use the cache after + // the first pull. + int64_t mLastEventTimeNs; + // Cache of data from last pull. If next request comes before cool down finishes, // cached data will be returned. // Cached data is cleared when diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp index 1a52eb928777..8a9ec7456e55 100644 --- a/cmds/statsd/src/external/StatsPullerManager.cpp +++ b/cmds/statsd/src/external/StatsPullerManager.cpp @@ -91,20 +91,21 @@ StatsPullerManager::StatsPullerManager() mPullAtomCallbackDeathRecipient(AIBinder_DeathRecipient_new(pullAtomCallbackDied)) { } -bool StatsPullerManager::Pull(int tagId, const ConfigKey& configKey, +bool StatsPullerManager::Pull(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs, vector<shared_ptr<LogEvent>>* data, bool useUids) { std::lock_guard<std::mutex> _l(mLock); - return PullLocked(tagId, configKey, data, useUids); + return PullLocked(tagId, configKey, eventTimeNs, data, useUids); } -bool StatsPullerManager::Pull(int tagId, const vector<int32_t>& uids, +bool StatsPullerManager::Pull(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool useUids) { std::lock_guard<std::mutex> _l(mLock); - return PullLocked(tagId, uids, data, useUids); + return PullLocked(tagId, uids, eventTimeNs, data, useUids); } bool StatsPullerManager::PullLocked(int tagId, const ConfigKey& configKey, - vector<shared_ptr<LogEvent>>* data, bool useUids) { + const int64_t eventTimeNs, vector<shared_ptr<LogEvent>>* data, + bool useUids) { vector<int32_t> uids; if (useUids) { auto uidProviderIt = mPullUidProviders.find(configKey); @@ -123,18 +124,19 @@ bool StatsPullerManager::PullLocked(int tagId, const ConfigKey& configKey, } uids = pullUidProvider->getPullAtomUids(tagId); } - return PullLocked(tagId, uids, data, useUids); + return PullLocked(tagId, uids, eventTimeNs, data, useUids); } bool StatsPullerManager::PullLocked(int tagId, const vector<int32_t>& uids, - vector<shared_ptr<LogEvent>>* data, bool useUids) { + const int64_t eventTimeNs, vector<shared_ptr<LogEvent>>* data, + bool useUids) { VLOG("Initiating pulling %d", tagId); if (useUids) { for (int32_t uid : uids) { PullerKey key = {.atomTag = tagId, .uid = uid}; auto pullerIt = kAllPullAtomInfo.find(key); if (pullerIt != kAllPullAtomInfo.end()) { - bool ret = pullerIt->second->Pull(data); + bool ret = pullerIt->second->Pull(eventTimeNs, data); VLOG("pulled %zu items", data->size()); if (!ret) { StatsdStats::getInstance().notePullFailed(tagId); @@ -149,7 +151,7 @@ bool StatsPullerManager::PullLocked(int tagId, const vector<int32_t>& uids, PullerKey key = {.atomTag = tagId, .uid = -1}; auto pullerIt = kAllPullAtomInfo.find(key); if (pullerIt != kAllPullAtomInfo.end()) { - bool ret = pullerIt->second->Pull(data); + bool ret = pullerIt->second->Pull(eventTimeNs, data); VLOG("pulled %zu items", data->size()); if (!ret) { StatsdStats::getInstance().notePullFailed(tagId); @@ -290,7 +292,8 @@ void StatsPullerManager::OnAlarmFired(int64_t elapsedTimeNs) { } for (const auto& pullInfo : needToPull) { vector<shared_ptr<LogEvent>> data; - bool pullSuccess = PullLocked(pullInfo.first->atomTag, pullInfo.first->configKey, &data); + bool pullSuccess = PullLocked(pullInfo.first->atomTag, pullInfo.first->configKey, + elapsedTimeNs, &data); if (!pullSuccess) { VLOG("pull failed at %lld, will try again later", (long long)elapsedTimeNs); } diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h index 5e18aaa6ed61..194a0f5edba8 100644 --- a/cmds/statsd/src/external/StatsPullerManager.h +++ b/cmds/statsd/src/external/StatsPullerManager.h @@ -101,11 +101,11 @@ public: // registered for any of the uids for this atom. // If the metric wants to make any change to the data, like timestamps, they // should make a copy as this data may be shared with multiple metrics. - virtual bool Pull(int tagId, const ConfigKey& configKey, + virtual bool Pull(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool useUids = true); // Same as above, but directly specify the allowed uids to pull from. - virtual bool Pull(int tagId, const vector<int32_t>& uids, + virtual bool Pull(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool useUids = true); // Clear pull data cache immediately. @@ -152,11 +152,11 @@ private: // mapping from Config Key to the PullUidProvider for that config std::map<ConfigKey, wp<PullUidProvider>> mPullUidProviders; - bool PullLocked(int tagId, const ConfigKey& configKey, vector<std::shared_ptr<LogEvent>>* data, - bool useUids = true); + bool PullLocked(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool useUids = true); - bool PullLocked(int tagId, const vector<int32_t>& uids, vector<std::shared_ptr<LogEvent>>* data, - bool useUids); + bool PullLocked(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool useUids); // locks for data receiver and StatsCompanionService changes std::mutex mLock; diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp index 21ffff32f539..d865c2176c1e 100644 --- a/cmds/statsd/src/metrics/CountMetricProducer.cpp +++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp @@ -122,11 +122,11 @@ CountMetricProducer::~CountMetricProducer() { } void CountMetricProducer::onStateChanged(const int64_t eventTimeNs, const int32_t atomId, - const HashableDimensionKey& primaryKey, int oldState, - int newState) { + const HashableDimensionKey& primaryKey, + const FieldValue& oldState, const FieldValue& newState) { VLOG("CountMetric %lld onStateChanged time %lld, State%d, key %s, %d -> %d", (long long)mMetricId, (long long)eventTimeNs, atomId, primaryKey.toString().c_str(), - oldState, newState); + oldState.mValue.int_value, newState.mValue.int_value); } void CountMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const { diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h index f9a8842efc3d..26b3d3cc6722 100644 --- a/cmds/statsd/src/metrics/CountMetricProducer.h +++ b/cmds/statsd/src/metrics/CountMetricProducer.h @@ -53,8 +53,8 @@ public: virtual ~CountMetricProducer(); void onStateChanged(const int64_t eventTimeNs, const int32_t atomId, - const HashableDimensionKey& primaryKey, int oldState, - int newState) override; + const HashableDimensionKey& primaryKey, const FieldValue& oldState, + const FieldValue& newState) override; protected: void onMatchedLogEventInternalLocked( diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp index 0de92f3d9f47..663365924829 100644 --- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp +++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp @@ -161,13 +161,12 @@ sp<AnomalyTracker> DurationMetricProducer::addAnomalyTracker( void DurationMetricProducer::onStateChanged(const int64_t eventTimeNs, const int32_t atomId, const HashableDimensionKey& primaryKey, - const int32_t oldState, const int32_t newState) { - // Create a FieldValue object to hold the new state. - FieldValue value; - value.mValue.setInt(newState); + const FieldValue& oldState, + const FieldValue& newState) { // Check if this metric has a StateMap. If so, map the new state value to // the correct state group id. - mapStateValue(atomId, &value); + FieldValue newStateCopy = newState; + mapStateValue(atomId, &newStateCopy); flushIfNeededLocked(eventTimeNs); @@ -185,7 +184,7 @@ void DurationMetricProducer::onStateChanged(const int64_t eventTimeNs, const int if (!containsLinkedStateValues(whatIt.first, primaryKey, mMetric2StateLinks, atomId)) { continue; } - whatIt.second->onStateChanged(eventTimeNs, atomId, value); + whatIt.second->onStateChanged(eventTimeNs, atomId, newStateCopy); } } diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h index 6f84076ee6b5..53f0f28c3386 100644 --- a/cmds/statsd/src/metrics/DurationMetricProducer.h +++ b/cmds/statsd/src/metrics/DurationMetricProducer.h @@ -55,8 +55,8 @@ public: const sp<AlarmMonitor>& anomalyAlarmMonitor) override; void onStateChanged(const int64_t eventTimeNs, const int32_t atomId, - const HashableDimensionKey& primaryKey, const int32_t oldState, - const int32_t newState) override; + const HashableDimensionKey& primaryKey, const FieldValue& oldState, + const FieldValue& newState) override; protected: void onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) override; diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp index cc4c56537c4c..1d4d0b3a5e5d 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp @@ -321,7 +321,7 @@ void GaugeMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) { return; } vector<std::shared_ptr<LogEvent>> allData; - if (!mPullerManager->Pull(mPullTagId, mConfigKey, &allData)) { + if (!mPullerManager->Pull(mPullTagId, mConfigKey, timestampNs, &allData)) { ALOGE("Gauge Stats puller failed for tag: %d at %lld", mPullTagId, (long long)timestampNs); return; } diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h index 91c98ea27269..e86fdf06e836 100644 --- a/cmds/statsd/src/metrics/MetricProducer.h +++ b/cmds/statsd/src/metrics/MetricProducer.h @@ -182,8 +182,8 @@ public: }; void onStateChanged(const int64_t eventTimeNs, const int32_t atomId, - const HashableDimensionKey& primaryKey, const int32_t oldState, - const int32_t newState){}; + const HashableDimensionKey& primaryKey, const FieldValue& oldState, + const FieldValue& newState){}; // Output the metrics data to [protoOutput]. All metrics reports end with the same timestamp. // This method clears all the past buckets. @@ -442,7 +442,7 @@ protected: bool mIsActive; // The slice_by_state atom ids defined in statsd_config. - std::vector<int32_t> mSlicedStateAtoms; + const std::vector<int32_t> mSlicedStateAtoms; // Maps atom ids and state values to group_ids (<atom_id, <value, group_id>>). const std::unordered_map<int32_t, std::unordered_map<int, int64_t>> mStateGroupMap; @@ -459,6 +459,7 @@ protected: FRIEND_TEST(CountMetricE2eTest, TestSlicedStateWithMap); FRIEND_TEST(CountMetricE2eTest, TestMultipleSlicedStates); FRIEND_TEST(CountMetricE2eTest, TestSlicedStateWithPrimaryFields); + FRIEND_TEST(CountMetricE2eTest, TestInitialConditionChanges); FRIEND_TEST(DurationMetricE2eTest, TestOneBucket); FRIEND_TEST(DurationMetricE2eTest, TestTwoBuckets); @@ -488,6 +489,7 @@ protected: FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState); FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions); FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions); + FRIEND_TEST(ValueMetricE2eTest, TestInitialConditionChanges); }; } // namespace statsd diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp index d7ad27bd9134..e8c575a1adea 100644 --- a/cmds/statsd/src/metrics/MetricsManager.cpp +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -71,6 +71,8 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config, mLastReportTimeNs(currentTimeNs), mLastReportWallClockNs(getWallClockNs()), mPullerManager(pullerManager), + mWhitelistedAtomIds(config.whitelisted_atom_ids().begin(), + config.whitelisted_atom_ids().end()), mShouldPersistHistory(config.persist_locally()) { // Init the ttl end timestamp. refreshTtl(timeBaseNs); @@ -366,11 +368,16 @@ void MetricsManager::onDumpReport(const int64_t dumpTimeStampNs, bool MetricsManager::checkLogCredentials(const LogEvent& event) { + // TODO(b/154856835): Remove this check once we get whitelist from the config. if (android::util::AtomsInfo::kWhitelistedAtoms.find(event.GetTagId()) != android::util::AtomsInfo::kWhitelistedAtoms.end()) { return true; } + + if (mWhitelistedAtomIds.find(event.GetTagId()) != mWhitelistedAtomIds.end()) { + return true; + } std::lock_guard<std::mutex> lock(mAllowedLogSourcesMutex); if (mAllowedLogSources.find(event.GetUid()) == mAllowedLogSources.end()) { VLOG("log source %d not on the whitelist", event.GetUid()); diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h index ef03d2064ab0..ad30a88c5d19 100644 --- a/cmds/statsd/src/metrics/MetricsManager.h +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -189,6 +189,8 @@ private: // To guard access to mAllowedLogSources mutable std::mutex mAllowedLogSourcesMutex; + const std::set<int32_t> mWhitelistedAtomIds; + // We can pull any atom from these uids. std::set<int32_t> mDefaultPullUids; @@ -290,9 +292,6 @@ private: FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation); FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition); FRIEND_TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents); - FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents); - FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm); - FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation); FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket); FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets); @@ -320,6 +319,7 @@ private: TestActivationOnBootMultipleActivationsDifferentActivationTypes); FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart); + FRIEND_TEST(CountMetricE2eTest, TestInitialConditionChanges); FRIEND_TEST(CountMetricE2eTest, TestSlicedState); FRIEND_TEST(CountMetricE2eTest, TestSlicedStateWithMap); FRIEND_TEST(CountMetricE2eTest, TestMultipleSlicedStates); @@ -337,6 +337,10 @@ private: FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSuperset); FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSubset); + FRIEND_TEST(ValueMetricE2eTest, TestInitialConditionChanges); + FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents); + FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm); + FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation); FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState); FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions); FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions); diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp index e5ec72e3d0f5..f03ce4550bc4 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -182,15 +182,26 @@ ValueMetricProducer::~ValueMetricProducer() { } void ValueMetricProducer::onStateChanged(int64_t eventTimeNs, int32_t atomId, - const HashableDimensionKey& primaryKey, int oldState, - int newState) { + const HashableDimensionKey& primaryKey, + const FieldValue& oldState, const FieldValue& newState) { VLOG("ValueMetric %lld onStateChanged time %lld, State %d, key %s, %d -> %d", (long long)mMetricId, (long long)eventTimeNs, atomId, primaryKey.toString().c_str(), - oldState, newState); + oldState.mValue.int_value, newState.mValue.int_value); // If condition is not true, we do not need to pull for this state change. if (mCondition != ConditionState::kTrue) { return; } + + // If old and new states are in the same StateGroup, then we do not need to + // pull for this state change. + FieldValue oldStateCopy = oldState; + FieldValue newStateCopy = newState; + mapStateValue(atomId, &oldStateCopy); + mapStateValue(atomId, &newStateCopy); + if (oldStateCopy == newStateCopy) { + return; + } + bool isEventLate = eventTimeNs < mCurrentBucketStartTimeNs; if (isEventLate) { VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs, @@ -508,7 +519,7 @@ void ValueMetricProducer::prepareFirstBucketLocked() { void ValueMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) { vector<std::shared_ptr<LogEvent>> allData; - if (!mPullerManager->Pull(mPullTagId, mConfigKey, &allData)) { + if (!mPullerManager->Pull(mPullTagId, mConfigKey, timestampNs, &allData)) { ALOGE("Stats puller failed for tag: %d at %lld", mPullTagId, (long long)timestampNs); invalidateCurrentBucket(timestampNs, BucketDropReason::PULL_FAILED); return; diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h index c8dc8cc290c4..751fef2bf2b1 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.h +++ b/cmds/statsd/src/metrics/ValueMetricProducer.h @@ -90,7 +90,7 @@ public: }; void onStateChanged(int64_t eventTimeNs, int32_t atomId, const HashableDimensionKey& primaryKey, - int oldState, int newState) override; + const FieldValue& oldState, const FieldValue& newState) override; protected: void onMatchedLogEventInternalLocked( diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp index 3ab44f4a06af..210d382b1363 100644 --- a/cmds/statsd/src/metrics/metrics_manager_util.cpp +++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp @@ -791,10 +791,19 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t } noReportMetricIds.insert(no_report_metric); } + + const set<int> whitelistedAtomIds(config.whitelisted_atom_ids().begin(), + config.whitelisted_atom_ids().end()); for (const auto& it : allMetricProducers) { // Register metrics to StateTrackers for (int atomId : it->getSlicedStateAtoms()) { - StateManager::getInstance().registerListener(atomId, it); + // Register listener for non-whitelisted atoms only. Using whitelisted atom as a sliced + // state atom is not allowed. + if (whitelistedAtomIds.find(atomId) == whitelistedAtomIds.end()) { + StateManager::getInstance().registerListener(atomId, it); + } else { + return false; + } } } return true; diff --git a/cmds/statsd/src/shell/ShellSubscriber.cpp b/cmds/statsd/src/shell/ShellSubscriber.cpp index 7b687210ce33..361b161c76ac 100644 --- a/cmds/statsd/src/shell/ShellSubscriber.cpp +++ b/cmds/statsd/src/shell/ShellSubscriber.cpp @@ -152,6 +152,7 @@ void ShellSubscriber::startPull(int myToken) { } int64_t nowMillis = getElapsedRealtimeMillis(); + int64_t nowNanos = getElapsedRealtimeNs(); for (PullInfo& pullInfo : mSubscriptionInfo->mPulledInfo) { if (pullInfo.mPrevPullElapsedRealtimeMs + pullInfo.mInterval >= nowMillis) { continue; @@ -161,7 +162,7 @@ void ShellSubscriber::startPull(int myToken) { getUidsForPullAtom(&uids, pullInfo); vector<std::shared_ptr<LogEvent>> data; - mPullerMgr->Pull(pullInfo.mPullerMatcher.atom_id(), uids, &data); + mPullerMgr->Pull(pullInfo.mPullerMatcher.atom_id(), uids, nowNanos, &data); VLOG("Pulled %zu atoms with id %d", data.size(), pullInfo.mPullerMatcher.atom_id()); writePulledAtomsLocked(data, pullInfo.mPullerMatcher); diff --git a/cmds/statsd/src/state/StateListener.h b/cmds/statsd/src/state/StateListener.h index d1af1968ac38..63880017ca18 100644 --- a/cmds/statsd/src/state/StateListener.h +++ b/cmds/statsd/src/state/StateListener.h @@ -45,8 +45,8 @@ public: * [newState]: Current state value after state change */ virtual void onStateChanged(const int64_t eventTimeNs, const int32_t atomId, - const HashableDimensionKey& primaryKey, int oldState, - int newState) = 0; + const HashableDimensionKey& primaryKey, const FieldValue& oldState, + const FieldValue& newState) = 0; }; } // namespace statsd diff --git a/cmds/statsd/src/state/StateTracker.cpp b/cmds/statsd/src/state/StateTracker.cpp index b63713b64c5d..41e525c343ba 100644 --- a/cmds/statsd/src/state/StateTracker.cpp +++ b/cmds/statsd/src/state/StateTracker.cpp @@ -35,31 +35,30 @@ void StateTracker::onLogEvent(const LogEvent& event) { HashableDimensionKey primaryKey; filterPrimaryKey(event.getValues(), &primaryKey); - FieldValue stateValue; - if (!getStateFieldValueFromLogEvent(event, &stateValue)) { + FieldValue newState; + if (!getStateFieldValueFromLogEvent(event, &newState)) { ALOGE("StateTracker error extracting state from log event. Missing exclusive state field."); clearStateForPrimaryKey(eventTimeNs, primaryKey); return; } - mField.setField(stateValue.mField.getField()); + mField.setField(newState.mField.getField()); - if (stateValue.mValue.getType() != INT) { + if (newState.mValue.getType() != INT) { ALOGE("StateTracker error extracting state from log event. Type: %d", - stateValue.mValue.getType()); + newState.mValue.getType()); clearStateForPrimaryKey(eventTimeNs, primaryKey); return; } - const int32_t resetState = event.getResetState(); - if (resetState != -1) { + if (int resetState = event.getResetState(); resetState != -1) { VLOG("StateTracker new reset state: %d", resetState); - handleReset(eventTimeNs, resetState); + const FieldValue resetStateFieldValue(mField, Value(resetState)); + handleReset(eventTimeNs, resetStateFieldValue); return; } - const int32_t newState = stateValue.mValue.int_value; - const bool nested = stateValue.mAnnotations.isNested(); + const bool nested = newState.mAnnotations.isNested(); StateValueInfo* stateValueInfo = &mStateMap[primaryKey]; updateStateForPrimaryKey(eventTimeNs, primaryKey, newState, nested, stateValueInfo); } @@ -85,7 +84,7 @@ bool StateTracker::getStateValue(const HashableDimensionKey& queryKey, FieldValu return false; } -void StateTracker::handleReset(const int64_t eventTimeNs, const int32_t newState) { +void StateTracker::handleReset(const int64_t eventTimeNs, const FieldValue& newState) { VLOG("StateTracker handle reset"); for (auto& [primaryKey, stateValueInfo] : mStateMap) { updateStateForPrimaryKey(eventTimeNs, primaryKey, newState, @@ -102,8 +101,9 @@ void StateTracker::clearStateForPrimaryKey(const int64_t eventTimeNs, // If there is no entry for the primaryKey in mStateMap, then the state is already // kStateUnknown. + const FieldValue state(mField, Value(kStateUnknown)); if (it != mStateMap.end()) { - updateStateForPrimaryKey(eventTimeNs, primaryKey, kStateUnknown, + updateStateForPrimaryKey(eventTimeNs, primaryKey, state, false /* nested; treat this state change as not nested */, &it->second); } @@ -111,22 +111,26 @@ void StateTracker::clearStateForPrimaryKey(const int64_t eventTimeNs, void StateTracker::updateStateForPrimaryKey(const int64_t eventTimeNs, const HashableDimensionKey& primaryKey, - const int32_t newState, const bool nested, + const FieldValue& newState, const bool nested, StateValueInfo* stateValueInfo) { - const int32_t oldState = stateValueInfo->state; + FieldValue oldState; + oldState.mField = mField; + oldState.mValue.setInt(stateValueInfo->state); + const int32_t oldStateValue = stateValueInfo->state; + const int32_t newStateValue = newState.mValue.int_value; - if (kStateUnknown == newState) { + if (kStateUnknown == newStateValue) { mStateMap.erase(primaryKey); } // Update state map for non-nested counting case. // Every state event triggers a state overwrite. if (!nested) { - stateValueInfo->state = newState; + stateValueInfo->state = newStateValue; stateValueInfo->count = 1; // Notify listeners if state has changed. - if (oldState != newState) { + if (oldStateValue != newStateValue) { notifyListeners(eventTimeNs, primaryKey, oldState, newState); } return; @@ -142,26 +146,26 @@ void StateTracker::updateStateForPrimaryKey(const int64_t eventTimeNs, // In atoms.proto, a state atom with nested counting enabled // must only have 2 states. There is no enforcemnt here of this requirement. // The atom must be logged correctly. - if (kStateUnknown == newState) { - if (kStateUnknown != oldState) { + if (kStateUnknown == newStateValue) { + if (kStateUnknown != oldStateValue) { notifyListeners(eventTimeNs, primaryKey, oldState, newState); } - } else if (oldState == kStateUnknown) { - stateValueInfo->state = newState; + } else if (oldStateValue == kStateUnknown) { + stateValueInfo->state = newStateValue; stateValueInfo->count = 1; notifyListeners(eventTimeNs, primaryKey, oldState, newState); - } else if (oldState == newState) { + } else if (oldStateValue == newStateValue) { stateValueInfo->count++; } else if (--stateValueInfo->count == 0) { - stateValueInfo->state = newState; + stateValueInfo->state = newStateValue; stateValueInfo->count = 1; notifyListeners(eventTimeNs, primaryKey, oldState, newState); } } void StateTracker::notifyListeners(const int64_t eventTimeNs, - const HashableDimensionKey& primaryKey, const int32_t oldState, - const int32_t newState) { + const HashableDimensionKey& primaryKey, + const FieldValue& oldState, const FieldValue& newState) { for (auto l : mListeners) { auto sl = l.promote(); if (sl != nullptr) { diff --git a/cmds/statsd/src/state/StateTracker.h b/cmds/statsd/src/state/StateTracker.h index c5f6315fc992..abd579e7e302 100644 --- a/cmds/statsd/src/state/StateTracker.h +++ b/cmds/statsd/src/state/StateTracker.h @@ -72,19 +72,19 @@ private: std::set<wp<StateListener>> mListeners; // Reset all state values in map to the given state. - void handleReset(const int64_t eventTimeNs, const int32_t newState); + void handleReset(const int64_t eventTimeNs, const FieldValue& newState); // Clears the state value mapped to the given primary key by setting it to kStateUnknown. void clearStateForPrimaryKey(const int64_t eventTimeNs, const HashableDimensionKey& primaryKey); // Update the StateMap based on the received state value. void updateStateForPrimaryKey(const int64_t eventTimeNs, const HashableDimensionKey& primaryKey, - const int32_t newState, const bool nested, + const FieldValue& newState, const bool nested, StateValueInfo* stateValueInfo); // Notify registered state listeners of state change. void notifyListeners(const int64_t eventTimeNs, const HashableDimensionKey& primaryKey, - const int32_t oldState, const int32_t newState); + const FieldValue& oldState, const FieldValue& newState); }; bool getStateFieldValueFromLogEvent(const LogEvent& event, FieldValue* output); diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto index c7407bd9af1e..2e6043df0e64 100644 --- a/cmds/statsd/src/statsd_config.proto +++ b/cmds/statsd/src/statsd_config.proto @@ -131,7 +131,7 @@ message SimplePredicate { UNKNOWN = 0; FALSE = 1; } - optional InitialValue initial_value = 5 [default = FALSE]; + optional InitialValue initial_value = 5 [default = UNKNOWN]; optional FieldMatcher dimensions = 6; } @@ -489,6 +489,8 @@ message StatsdConfig { repeated PullAtomPackages pull_atom_packages = 23; + repeated int32 whitelisted_atom_ids = 24; + // Field number 1000 is reserved for later use. reserved 1000; } |