diff options
Diffstat (limited to 'cmds')
41 files changed, 1248 insertions, 474 deletions
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp index 9e6d0a23de10..dc1612575f38 100644 --- a/cmds/incidentd/src/IncidentService.cpp +++ b/cmds/incidentd/src/IncidentService.cpp @@ -351,9 +351,9 @@ Status IncidentService::reportIncidentToDumpstate(unique_fd stream, Status IncidentService::registerSection(const int id, const String16& name16, const sp<IIncidentDumpCallback>& callback) { - const char* name = String8(name16).c_str(); + const String8 name = String8(name16); const uid_t callingUid = IPCThreadState::self()->getCallingUid(); - ALOGI("Uid %d registers section %d '%s'", callingUid, id, name); + ALOGI("Uid %d registers section %d '%s'", callingUid, id, name.c_str()); if (callback == nullptr) { return Status::fromExceptionCode(Status::EX_NULL_POINTER); } @@ -363,11 +363,11 @@ Status IncidentService::registerSection(const int id, const String16& name16, ALOGW("Error registering section %d: calling uid does not match", id); return Status::fromExceptionCode(Status::EX_SECURITY); } - mRegisteredSections.at(i) = new BringYourOwnSection(id, name, callingUid, callback); + mRegisteredSections.at(i) = new BringYourOwnSection(id, name.c_str(), callingUid, callback); return Status::ok(); } } - mRegisteredSections.push_back(new BringYourOwnSection(id, name, callingUid, callback)); + mRegisteredSections.push_back(new BringYourOwnSection(id, name.c_str(), callingUid, callback)); return Status::ok(); } diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp index 114cbb8d6460..61e5eb07130c 100644 --- a/cmds/incidentd/src/Section.cpp +++ b/cmds/incidentd/src/Section.cpp @@ -876,7 +876,9 @@ BringYourOwnSection::~BringYourOwnSection() {} status_t BringYourOwnSection::BlockingCall(unique_fd& pipeWriteFd) const { android::os::ParcelFileDescriptor pfd(std::move(pipeWriteFd)); - mCallback->onDumpSection(pfd); + if(mCallback != nullptr) { + mCallback->onDumpSection(pfd); + } return NO_ERROR; } diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h index 2ce45ed66a32..bc4909dcfa2e 100644 --- a/cmds/incidentd/src/Section.h +++ b/cmds/incidentd/src/Section.h @@ -207,7 +207,7 @@ public: virtual status_t BlockingCall(unique_fd& pipeWriteFd) const; private: - const sp<IIncidentDumpCallback>& mCallback; + const sp<IIncidentDumpCallback> mCallback; }; 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; } diff --git a/cmds/statsd/tests/MetricsManager_test.cpp b/cmds/statsd/tests/MetricsManager_test.cpp index 3890fbe7dc6f..b3b095bf4bff 100644 --- a/cmds/statsd/tests/MetricsManager_test.cpp +++ b/cmds/statsd/tests/MetricsManager_test.cpp @@ -29,6 +29,7 @@ #include "src/metrics/MetricProducer.h" #include "src/metrics/ValueMetricProducer.h" #include "src/metrics/metrics_manager_util.h" +#include "src/state/StateManager.h" #include "statsd_test_util.h" using namespace testing; @@ -591,6 +592,58 @@ TEST(MetricsManagerTest, TestLogSources) { EXPECT_TRUE(isSubset(defaultPullUids, set<int32_t>(atom3Uids.begin(), atom3Uids.end()))); } +TEST(MetricsManagerTest, TestCheckLogCredentialsWhitelistedAtom) { + sp<UidMap> uidMap; + sp<StatsPullerManager> pullerManager = new StatsPullerManager(); + sp<AlarmMonitor> anomalyAlarmMonitor; + sp<AlarmMonitor> periodicAlarmMonitor; + + StatsdConfig config = buildGoodConfig(); + config.add_whitelisted_atom_ids(3); + config.add_whitelisted_atom_ids(4); + + MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap, + pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor); + + LogEvent event(0 /* uid */, 0 /* pid */); + CreateNoValuesLogEvent(&event, 10 /* atom id */, 0 /* timestamp */); + EXPECT_FALSE(metricsManager.checkLogCredentials(event)); + + CreateNoValuesLogEvent(&event, 3 /* atom id */, 0 /* timestamp */); + EXPECT_TRUE(metricsManager.checkLogCredentials(event)); + + CreateNoValuesLogEvent(&event, 4 /* atom id */, 0 /* timestamp */); + EXPECT_TRUE(metricsManager.checkLogCredentials(event)); +} + +TEST(MetricsManagerTest, TestWhitelistedAtomStateTracker) { + sp<UidMap> uidMap; + sp<StatsPullerManager> pullerManager = new StatsPullerManager(); + sp<AlarmMonitor> anomalyAlarmMonitor; + sp<AlarmMonitor> periodicAlarmMonitor; + + StatsdConfig config = buildGoodConfig(); + config.add_allowed_log_source("AID_SYSTEM"); + config.add_whitelisted_atom_ids(3); + config.add_whitelisted_atom_ids(4); + + State state; + state.set_id(1); + state.set_atom_id(3); + + *config.add_state() = state; + + config.mutable_count_metric(0)->add_slice_by_state(state.id()); + + StateManager::getInstance().clear(); + + MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap, + pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor); + + EXPECT_EQ(0, StateManager::getInstance().getStateTrackersCount()); + EXPECT_FALSE(metricsManager.isConfigValid()); +} + } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp index 1a7cd5584f3d..04eb40080631 100644 --- a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp @@ -28,6 +28,92 @@ namespace statsd { #ifdef __ANDROID__ /** + * Tests the initial condition and condition after the first log events for + * count metrics with either a combination condition or simple condition. + * + * Metrics should be initialized with condition kUnknown (given that the + * predicate is using the default InitialValue of UNKNOWN). The condition should + * be updated to either kFalse or kTrue if a condition event is logged for all + * children conditions. + */ +TEST(CountMetricE2eTest, TestInitialConditionChanges) { + // Initialize config. + StatsdConfig config; + config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. + config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root. + + auto syncStartMatcher = CreateSyncStartAtomMatcher(); + *config.add_atom_matcher() = syncStartMatcher; + *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); + *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); + *config.add_atom_matcher() = CreateBatteryStateNoneMatcher(); + *config.add_atom_matcher() = CreateBatteryStateUsbMatcher(); + + auto screenOnPredicate = CreateScreenIsOnPredicate(); + *config.add_predicate() = screenOnPredicate; + + auto deviceUnpluggedPredicate = CreateDeviceUnpluggedPredicate(); + *config.add_predicate() = deviceUnpluggedPredicate; + + auto screenOnOnBatteryPredicate = config.add_predicate(); + screenOnOnBatteryPredicate->set_id(StringToId("screenOnOnBatteryPredicate")); + screenOnOnBatteryPredicate->mutable_combination()->set_operation(LogicalOperation::AND); + addPredicateToPredicateCombination(screenOnPredicate, screenOnOnBatteryPredicate); + addPredicateToPredicateCombination(deviceUnpluggedPredicate, screenOnOnBatteryPredicate); + + // CountSyncStartWhileScreenOnOnBattery (CombinationCondition) + CountMetric* countMetric1 = config.add_count_metric(); + countMetric1->set_id(StringToId("CountSyncStartWhileScreenOnOnBattery")); + countMetric1->set_what(syncStartMatcher.id()); + countMetric1->set_condition(screenOnOnBatteryPredicate->id()); + countMetric1->set_bucket(FIVE_MINUTES); + + // CountSyncStartWhileOnBattery (SimpleCondition) + CountMetric* countMetric2 = config.add_count_metric(); + countMetric2->set_id(StringToId("CountSyncStartWhileOnBatterySliceScreen")); + countMetric2->set_what(syncStartMatcher.id()); + countMetric2->set_condition(deviceUnpluggedPredicate.id()); + countMetric2->set_bucket(FIVE_MINUTES); + + const uint64_t bucketStartTimeNs = 10000000000; // 0:10 + const uint64_t bucketSizeNs = + TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL; + int uid = 12345; + int64_t cfgId = 98765; + ConfigKey cfgKey(uid, cfgId); + auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); + + EXPECT_EQ(processor->mMetricsManagers.size(), 1u); + sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second; + EXPECT_TRUE(metricsManager->isConfigValid()); + EXPECT_EQ(2, metricsManager->mAllMetricProducers.size()); + + sp<MetricProducer> metricProducer1 = metricsManager->mAllMetricProducers[0]; + sp<MetricProducer> metricProducer2 = metricsManager->mAllMetricProducers[1]; + + EXPECT_EQ(ConditionState::kUnknown, metricProducer1->mCondition); + EXPECT_EQ(ConditionState::kUnknown, metricProducer2->mCondition); + + auto screenOnEvent = + CreateScreenStateChangedEvent(bucketStartTimeNs + 30, android::view::DISPLAY_STATE_ON); + processor->OnLogEvent(screenOnEvent.get()); + EXPECT_EQ(ConditionState::kUnknown, metricProducer1->mCondition); + EXPECT_EQ(ConditionState::kUnknown, metricProducer2->mCondition); + + auto pluggedUsbEvent = CreateBatteryStateChangedEvent( + bucketStartTimeNs + 50, BatteryPluggedStateEnum::BATTERY_PLUGGED_USB); + processor->OnLogEvent(pluggedUsbEvent.get()); + EXPECT_EQ(ConditionState::kFalse, metricProducer1->mCondition); + EXPECT_EQ(ConditionState::kFalse, metricProducer2->mCondition); + + auto pluggedNoneEvent = CreateBatteryStateChangedEvent( + bucketStartTimeNs + 70, BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE); + processor->OnLogEvent(pluggedNoneEvent.get()); + EXPECT_EQ(ConditionState::kTrue, metricProducer1->mCondition); + EXPECT_EQ(ConditionState::kTrue, metricProducer2->mCondition); +} + +/** * Test a count metric that has one slice_by_state with no primary fields. * * Once the CountMetricProducer is initialized, it has one atom id in @@ -85,7 +171,7 @@ TEST(CountMetricE2eTest, TestSlicedState) { x x x x x x (syncStartEvents) | | (ScreenIsOnEvent) | | (ScreenIsOffEvent) - | (ScreenUnknownEvent) + | (ScreenDozeEvent) */ // Initialize log events - first bucket. std::vector<int> attributionUids1 = {123}; @@ -243,9 +329,8 @@ TEST(CountMetricE2eTest, TestSlicedStateWithMap) { |-----------------------------|-----------------------------|-- x x x x x x x x x (syncStartEvents) -----------------------------------------------------------SCREEN_OFF events - | (ScreenStateUnknownEvent = 0) | | (ScreenStateOffEvent = 1) - | (ScreenStateDozeEvent = 3) + | | (ScreenStateDozeEvent = 3) | (ScreenStateDozeSuspendEvent = 4) -----------------------------------------------------------SCREEN_ON events @@ -262,7 +347,7 @@ TEST(CountMetricE2eTest, TestSlicedStateWithMap) { attributionTags1, "sync_name")); // 0:30 events.push_back(CreateScreenStateChangedEvent( bucketStartTimeNs + 30 * NS_PER_SEC, - android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN)); // 0:40 + android::view::DisplayStateEnum::DISPLAY_STATE_DOZE)); // 0:40 events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 60 * NS_PER_SEC, attributionUids1, attributionTags1, "sync_name")); // 1:10 events.push_back(CreateScreenStateChangedEvent( @@ -625,9 +710,8 @@ TEST(CountMetricE2eTest, TestMultipleSlicedStates) { |------------------------|------------------------|-- 1 1 1 1 1 2 1 1 2 (AppCrashEvents) ---------------------------------------------------SCREEN_OFF events - | (ScreenUnknownEvent = 0) | | (ScreenOffEvent = 1) - | (ScreenDozeEvent = 3) + | | (ScreenDozeEvent = 3) ---------------------------------------------------SCREEN_ON events | | (ScreenOnEvent = 2) | (ScreenOnSuspendEvent = 6) @@ -660,7 +744,7 @@ TEST(CountMetricE2eTest, TestMultipleSlicedStates) { CreateAppCrashOccurredEvent(bucketStartTimeNs + 20 * NS_PER_SEC, 1 /*uid*/)); // 0:30 events.push_back(CreateScreenStateChangedEvent( bucketStartTimeNs + 30 * NS_PER_SEC, - android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN)); // 0:40 + android::view::DisplayStateEnum::DISPLAY_STATE_DOZE)); // 0:40 events.push_back( CreateAppCrashOccurredEvent(bucketStartTimeNs + 60 * NS_PER_SEC, 1 /*uid*/)); // 1:10 events.push_back(CreateUidProcessStateChangedEvent( diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp index e595f290ffdf..4d3928277527 100644 --- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp @@ -63,8 +63,143 @@ StatsdConfig CreateStatsdConfig(bool useCondition = true) { return config; } +StatsdConfig CreateStatsdConfigWithStates() { + StatsdConfig config; + config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. + config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root. + + auto pulledAtomMatcher = CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE); + *config.add_atom_matcher() = pulledAtomMatcher; + *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); + *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); + *config.add_atom_matcher() = CreateBatteryStateNoneMatcher(); + *config.add_atom_matcher() = CreateBatteryStateUsbMatcher(); + + auto screenOnPredicate = CreateScreenIsOnPredicate(); + *config.add_predicate() = screenOnPredicate; + + auto screenOffPredicate = CreateScreenIsOffPredicate(); + *config.add_predicate() = screenOffPredicate; + + auto deviceUnpluggedPredicate = CreateDeviceUnpluggedPredicate(); + *config.add_predicate() = deviceUnpluggedPredicate; + + auto screenOnOnBatteryPredicate = config.add_predicate(); + screenOnOnBatteryPredicate->set_id(StringToId("screenOnOnBatteryPredicate")); + screenOnOnBatteryPredicate->mutable_combination()->set_operation(LogicalOperation::AND); + addPredicateToPredicateCombination(screenOnPredicate, screenOnOnBatteryPredicate); + addPredicateToPredicateCombination(deviceUnpluggedPredicate, screenOnOnBatteryPredicate); + + auto screenOffOnBatteryPredicate = config.add_predicate(); + screenOffOnBatteryPredicate->set_id(StringToId("ScreenOffOnBattery")); + screenOffOnBatteryPredicate->mutable_combination()->set_operation(LogicalOperation::AND); + addPredicateToPredicateCombination(screenOffPredicate, screenOffOnBatteryPredicate); + addPredicateToPredicateCombination(deviceUnpluggedPredicate, screenOffOnBatteryPredicate); + + const State screenState = + CreateScreenStateWithSimpleOnOffMap(/*screen on id=*/321, /*screen off id=*/123); + *config.add_state() = screenState; + + // ValueMetricSubsystemSleepWhileScreenOnOnBattery + auto valueMetric1 = config.add_value_metric(); + valueMetric1->set_id(metricId); + valueMetric1->set_what(pulledAtomMatcher.id()); + valueMetric1->set_condition(screenOnOnBatteryPredicate->id()); + *valueMetric1->mutable_value_field() = + CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); + valueMetric1->set_bucket(FIVE_MINUTES); + valueMetric1->set_use_absolute_value_on_reset(true); + valueMetric1->set_skip_zero_diff_output(false); + valueMetric1->set_max_pull_delay_sec(INT_MAX); + + // ValueMetricSubsystemSleepWhileScreenOffOnBattery + ValueMetric* valueMetric2 = config.add_value_metric(); + valueMetric2->set_id(StringToId("ValueMetricSubsystemSleepWhileScreenOffOnBattery")); + valueMetric2->set_what(pulledAtomMatcher.id()); + valueMetric2->set_condition(screenOffOnBatteryPredicate->id()); + *valueMetric2->mutable_value_field() = + CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); + valueMetric2->set_bucket(FIVE_MINUTES); + valueMetric2->set_use_absolute_value_on_reset(true); + valueMetric2->set_skip_zero_diff_output(false); + valueMetric2->set_max_pull_delay_sec(INT_MAX); + + // ValueMetricSubsystemSleepWhileOnBatterySliceScreen + ValueMetric* valueMetric3 = config.add_value_metric(); + valueMetric3->set_id(StringToId("ValueMetricSubsystemSleepWhileOnBatterySliceScreen")); + valueMetric3->set_what(pulledAtomMatcher.id()); + valueMetric3->set_condition(deviceUnpluggedPredicate.id()); + *valueMetric3->mutable_value_field() = + CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); + valueMetric3->add_slice_by_state(screenState.id()); + valueMetric3->set_bucket(FIVE_MINUTES); + valueMetric3->set_use_absolute_value_on_reset(true); + valueMetric3->set_skip_zero_diff_output(false); + valueMetric3->set_max_pull_delay_sec(INT_MAX); + return config; +} + } // namespace +/** + * Tests the initial condition and condition after the first log events for + * value metrics with either a combination condition or simple condition. + * + * Metrics should be initialized with condition kUnknown (given that the + * predicate is using the default InitialValue of UNKNOWN). The condition should + * be updated to either kFalse or kTrue if a condition event is logged for all + * children conditions. + */ +TEST(ValueMetricE2eTest, TestInitialConditionChanges) { + StatsdConfig config = CreateStatsdConfigWithStates(); + int64_t baseTimeNs = getElapsedRealtimeNs(); + int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs; + int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000; + + ConfigKey cfgKey; + int32_t tagId = util::SUBSYSTEM_SLEEP_STATE; + auto processor = + CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey, + SharedRefBase::make<FakeSubsystemSleepCallback>(), tagId); + + EXPECT_EQ(processor->mMetricsManagers.size(), 1u); + sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second; + EXPECT_TRUE(metricsManager->isConfigValid()); + EXPECT_EQ(3, metricsManager->mAllMetricProducers.size()); + + // Combination condition metric - screen on and device unplugged + sp<MetricProducer> metricProducer1 = metricsManager->mAllMetricProducers[0]; + // Simple condition metric - device unplugged + sp<MetricProducer> metricProducer2 = metricsManager->mAllMetricProducers[2]; + + EXPECT_EQ(ConditionState::kUnknown, metricProducer1->mCondition); + EXPECT_EQ(ConditionState::kUnknown, metricProducer2->mCondition); + + auto screenOnEvent = + CreateScreenStateChangedEvent(configAddedTimeNs + 30, android::view::DISPLAY_STATE_ON); + processor->OnLogEvent(screenOnEvent.get()); + EXPECT_EQ(ConditionState::kUnknown, metricProducer1->mCondition); + EXPECT_EQ(ConditionState::kUnknown, metricProducer2->mCondition); + + auto screenOffEvent = + CreateScreenStateChangedEvent(configAddedTimeNs + 40, android::view::DISPLAY_STATE_OFF); + processor->OnLogEvent(screenOffEvent.get()); + EXPECT_EQ(ConditionState::kUnknown, metricProducer1->mCondition); + EXPECT_EQ(ConditionState::kUnknown, metricProducer2->mCondition); + + auto pluggedUsbEvent = CreateBatteryStateChangedEvent( + configAddedTimeNs + 50, BatteryPluggedStateEnum::BATTERY_PLUGGED_USB); + processor->OnLogEvent(pluggedUsbEvent.get()); + EXPECT_EQ(ConditionState::kFalse, metricProducer1->mCondition); + EXPECT_EQ(ConditionState::kFalse, metricProducer2->mCondition); + + auto pluggedNoneEvent = CreateBatteryStateChangedEvent( + configAddedTimeNs + 70, BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE); + processor->OnLogEvent(pluggedNoneEvent.get()); + EXPECT_EQ(ConditionState::kFalse, metricProducer1->mCondition); + EXPECT_EQ(ConditionState::kTrue, metricProducer2->mCondition); +} + TEST(ValueMetricE2eTest, TestPulledEvents) { auto config = CreateStatsdConfig(); int64_t baseTimeNs = getElapsedRealtimeNs(); diff --git a/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp b/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp index e37c72ed0ee3..13cdfc292d49 100644 --- a/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp +++ b/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp @@ -155,7 +155,7 @@ TEST_F(StatsCallbackPullerTest, PullFail) { TEST_F(StatsCallbackPullerTest, PullTimeout) { shared_ptr<FakePullAtomCallback> cb = SharedRefBase::make<FakePullAtomCallback>(); pullSuccess = true; - pullDelayNs = 500000000; // 500ms. + pullDelayNs = MillisToNano(5); // 5ms. pullTimeoutNs = 10000; // 10 microseconds. int64_t value = 4321; values.push_back(value); @@ -184,7 +184,7 @@ TEST_F(StatsCallbackPullerTest, PullTimeout) { TEST_F(StatsCallbackPullerTest, RegisterAndTimeout) { shared_ptr<FakePullAtomCallback> cb = SharedRefBase::make<FakePullAtomCallback>(); pullSuccess = true; - pullDelayNs = 500000000; // 500 ms. + pullDelayNs = MillisToNano(5); // 5 ms. pullTimeoutNs = 10000; // 10 microsseconds. int64_t value = 4321; int32_t uid = 123; @@ -196,7 +196,7 @@ TEST_F(StatsCallbackPullerTest, RegisterAndTimeout) { vector<shared_ptr<LogEvent>> dataHolder; int64_t startTimeNs = getElapsedRealtimeNs(); // Returns false, since StatsPuller code will evaluate the timeout. - EXPECT_FALSE(pullerManager->Pull(pullTagId, {uid}, &dataHolder)); + EXPECT_FALSE(pullerManager->Pull(pullTagId, {uid}, startTimeNs, &dataHolder)); int64_t endTimeNs = getElapsedRealtimeNs(); int64_t actualPullDurationNs = endTimeNs - startTimeNs; diff --git a/cmds/statsd/tests/external/StatsPullerManager_test.cpp b/cmds/statsd/tests/external/StatsPullerManager_test.cpp index 6b3f4cccb95b..c76e85ec75e6 100644 --- a/cmds/statsd/tests/external/StatsPullerManager_test.cpp +++ b/cmds/statsd/tests/external/StatsPullerManager_test.cpp @@ -101,14 +101,14 @@ TEST(StatsPullerManagerTest, TestPullInvalidUid) { sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister(); vector<shared_ptr<LogEvent>> data; - EXPECT_FALSE(pullerManager->Pull(pullTagId1, {unregisteredUid}, &data, true)); + EXPECT_FALSE(pullerManager->Pull(pullTagId1, {unregisteredUid}, /*timestamp =*/1, &data, true)); } TEST(StatsPullerManagerTest, TestPullChoosesCorrectUid) { sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister(); vector<shared_ptr<LogEvent>> data; - EXPECT_TRUE(pullerManager->Pull(pullTagId1, {uid1}, &data, true)); + EXPECT_TRUE(pullerManager->Pull(pullTagId1, {uid1}, /*timestamp =*/1, &data, true)); ASSERT_EQ(data.size(), 1); EXPECT_EQ(data[0]->GetTagId(), pullTagId1); ASSERT_EQ(data[0]->getValues().size(), 1); @@ -121,7 +121,7 @@ TEST(StatsPullerManagerTest, TestPullInvalidConfigKey) { pullerManager->RegisterPullUidProvider(configKey, uidProvider); vector<shared_ptr<LogEvent>> data; - EXPECT_FALSE(pullerManager->Pull(pullTagId1, badConfigKey, &data, true)); + EXPECT_FALSE(pullerManager->Pull(pullTagId1, badConfigKey, /*timestamp =*/1, &data, true)); } TEST(StatsPullerManagerTest, TestPullConfigKeyGood) { @@ -130,7 +130,7 @@ TEST(StatsPullerManagerTest, TestPullConfigKeyGood) { pullerManager->RegisterPullUidProvider(configKey, uidProvider); vector<shared_ptr<LogEvent>> data; - EXPECT_TRUE(pullerManager->Pull(pullTagId1, configKey, &data, true)); + EXPECT_TRUE(pullerManager->Pull(pullTagId1, configKey, /*timestamp =*/1, &data, true)); EXPECT_EQ(data[0]->GetTagId(), pullTagId1); ASSERT_EQ(data[0]->getValues().size(), 1); EXPECT_EQ(data[0]->getValues()[0].mValue.int_value, uid2); @@ -142,7 +142,7 @@ TEST(StatsPullerManagerTest, TestPullConfigKeyNoPullerWithUid) { pullerManager->RegisterPullUidProvider(configKey, uidProvider); vector<shared_ptr<LogEvent>> data; - EXPECT_FALSE(pullerManager->Pull(pullTagId2, configKey, &data, true)); + EXPECT_FALSE(pullerManager->Pull(pullTagId2, configKey, /*timestamp =*/1, &data, true)); } } // namespace statsd diff --git a/cmds/statsd/tests/external/StatsPuller_test.cpp b/cmds/statsd/tests/external/StatsPuller_test.cpp index 02a43e4e179a..55a90365e151 100644 --- a/cmds/statsd/tests/external/StatsPuller_test.cpp +++ b/cmds/statsd/tests/external/StatsPuller_test.cpp @@ -39,7 +39,6 @@ using std::this_thread::sleep_for; using testing::Contains; namespace { -// cooldown time 1sec. int pullTagId = 10014; bool pullSuccess; @@ -48,7 +47,8 @@ long pullDelayNs; class FakePuller : public StatsPuller { public: - FakePuller() : StatsPuller(pullTagId, /*coolDown=*/NS_PER_SEC, /*timeout=*/NS_PER_SEC / 2){}; + FakePuller() + : StatsPuller(pullTagId, /*coolDownNs=*/MillisToNano(10), /*timeoutNs=*/MillisToNano(5)){}; private: bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override { @@ -92,21 +92,21 @@ TEST_F(StatsPullerTest, PullSuccess) { pullSuccess = true; vector<std::shared_ptr<LogEvent>> dataHolder; - EXPECT_TRUE(puller.Pull(&dataHolder)); + EXPECT_TRUE(puller.Pull(getElapsedRealtimeNs(), &dataHolder)); ASSERT_EQ(1, dataHolder.size()); EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId()); EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs()); ASSERT_EQ(1, dataHolder[0]->size()); EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value); - sleep_for(std::chrono::seconds(1)); + sleep_for(std::chrono::milliseconds(11)); pullData.clear(); pullData.push_back(createSimpleEvent(2222L, 44)); pullSuccess = true; - EXPECT_TRUE(puller.Pull(&dataHolder)); + EXPECT_TRUE(puller.Pull(getElapsedRealtimeNs(), &dataHolder)); ASSERT_EQ(1, dataHolder.size()); EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId()); EXPECT_EQ(2222L, dataHolder[0]->GetElapsedTimestampNs()); @@ -120,26 +120,27 @@ TEST_F(StatsPullerTest, PullFailAfterSuccess) { pullSuccess = true; vector<std::shared_ptr<LogEvent>> dataHolder; - EXPECT_TRUE(puller.Pull(&dataHolder)); + EXPECT_TRUE(puller.Pull(getElapsedRealtimeNs(), &dataHolder)); ASSERT_EQ(1, dataHolder.size()); EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId()); EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs()); ASSERT_EQ(1, dataHolder[0]->size()); EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value); - sleep_for(std::chrono::seconds(1)); + sleep_for(std::chrono::milliseconds(11)); pullData.clear(); pullData.push_back(createSimpleEvent(2222L, 44)); pullSuccess = false; dataHolder.clear(); - EXPECT_FALSE(puller.Pull(&dataHolder)); + EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder)); ASSERT_EQ(0, dataHolder.size()); + // Fails due to hitting the cool down. pullSuccess = true; dataHolder.clear(); - EXPECT_FALSE(puller.Pull(&dataHolder)); + EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder)); ASSERT_EQ(0, dataHolder.size()); } @@ -147,19 +148,20 @@ TEST_F(StatsPullerTest, PullFailAfterSuccess) { TEST_F(StatsPullerTest, PullTakeTooLongAndPullFast) { pullData.push_back(createSimpleEvent(1111L, 33)); pullSuccess = true; - // timeout is 0.5 - pullDelayNs = (long)(0.8 * NS_PER_SEC); + // timeout is 5ms + pullDelayNs = MillisToNano(6); vector<std::shared_ptr<LogEvent>> dataHolder; - EXPECT_FALSE(puller.Pull(&dataHolder)); + EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder)); ASSERT_EQ(0, dataHolder.size()); pullData.clear(); pullData.push_back(createSimpleEvent(2222L, 44)); + pullDelayNs = 0; pullSuccess = true; dataHolder.clear(); - EXPECT_FALSE(puller.Pull(&dataHolder)); + EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder)); ASSERT_EQ(0, dataHolder.size()); } @@ -169,7 +171,7 @@ TEST_F(StatsPullerTest, PullFail) { pullSuccess = false; vector<std::shared_ptr<LogEvent>> dataHolder; - EXPECT_FALSE(puller.Pull(&dataHolder)); + EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder)); ASSERT_EQ(0, dataHolder.size()); } @@ -177,10 +179,10 @@ TEST_F(StatsPullerTest, PullTakeTooLong) { pullData.push_back(createSimpleEvent(1111L, 33)); pullSuccess = true; - pullDelayNs = NS_PER_SEC; + pullDelayNs = MillisToNano(6); vector<std::shared_ptr<LogEvent>> dataHolder; - EXPECT_FALSE(puller.Pull(&dataHolder)); + EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder)); ASSERT_EQ(0, dataHolder.size()); } @@ -190,7 +192,7 @@ TEST_F(StatsPullerTest, PullTooFast) { pullSuccess = true; vector<std::shared_ptr<LogEvent>> dataHolder; - EXPECT_TRUE(puller.Pull(&dataHolder)); + EXPECT_TRUE(puller.Pull(getElapsedRealtimeNs(), &dataHolder)); ASSERT_EQ(1, dataHolder.size()); EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId()); EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs()); @@ -203,7 +205,7 @@ TEST_F(StatsPullerTest, PullTooFast) { pullSuccess = true; dataHolder.clear(); - EXPECT_TRUE(puller.Pull(&dataHolder)); + EXPECT_TRUE(puller.Pull(getElapsedRealtimeNs(), &dataHolder)); ASSERT_EQ(1, dataHolder.size()); EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId()); EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs()); @@ -217,7 +219,7 @@ TEST_F(StatsPullerTest, PullFailsAndTooFast) { pullSuccess = false; vector<std::shared_ptr<LogEvent>> dataHolder; - EXPECT_FALSE(puller.Pull(&dataHolder)); + EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder)); ASSERT_EQ(0, dataHolder.size()); pullData.clear(); @@ -225,7 +227,84 @@ TEST_F(StatsPullerTest, PullFailsAndTooFast) { pullSuccess = true; - EXPECT_FALSE(puller.Pull(&dataHolder)); + EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder)); + ASSERT_EQ(0, dataHolder.size()); +} + +TEST_F(StatsPullerTest, PullSameEventTime) { + pullData.push_back(createSimpleEvent(1111L, 33)); + + pullSuccess = true; + int64_t eventTimeNs = getElapsedRealtimeNs(); + + vector<std::shared_ptr<LogEvent>> dataHolder; + EXPECT_TRUE(puller.Pull(eventTimeNs, &dataHolder)); + ASSERT_EQ(1, dataHolder.size()); + EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId()); + EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs()); + ASSERT_EQ(1, dataHolder[0]->size()); + EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value); + + pullData.clear(); + pullData.push_back(createSimpleEvent(2222L, 44)); + + // Sleep to ensure the cool down expires. + sleep_for(std::chrono::milliseconds(11)); + pullSuccess = true; + + dataHolder.clear(); + EXPECT_TRUE(puller.Pull(eventTimeNs, &dataHolder)); + ASSERT_EQ(1, dataHolder.size()); + EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId()); + EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs()); + ASSERT_EQ(1, dataHolder[0]->size()); + EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value); +} + +// Test pull takes longer than timeout, 2nd pull happens at same event time +TEST_F(StatsPullerTest, PullTakeTooLongAndPullSameEventTime) { + pullData.push_back(createSimpleEvent(1111L, 33)); + pullSuccess = true; + int64_t eventTimeNs = getElapsedRealtimeNs(); + // timeout is 5ms + pullDelayNs = MillisToNano(6); + + vector<std::shared_ptr<LogEvent>> dataHolder; + EXPECT_FALSE(puller.Pull(eventTimeNs, &dataHolder)); + ASSERT_EQ(0, dataHolder.size()); + + // Sleep to ensure the cool down expires. 6ms is taken by the delay, so only 5 is needed here. + sleep_for(std::chrono::milliseconds(5)); + + pullData.clear(); + pullData.push_back(createSimpleEvent(2222L, 44)); + pullDelayNs = 0; + + pullSuccess = true; + dataHolder.clear(); + EXPECT_FALSE(puller.Pull(eventTimeNs, &dataHolder)); + ASSERT_EQ(0, dataHolder.size()); +} + +TEST_F(StatsPullerTest, PullFailsAndPullSameEventTime) { + pullData.push_back(createSimpleEvent(1111L, 33)); + + pullSuccess = false; + int64_t eventTimeNs = getElapsedRealtimeNs(); + + vector<std::shared_ptr<LogEvent>> dataHolder; + EXPECT_FALSE(puller.Pull(eventTimeNs, &dataHolder)); + ASSERT_EQ(0, dataHolder.size()); + + // Sleep to ensure the cool down expires. + sleep_for(std::chrono::milliseconds(11)); + + pullData.clear(); + pullData.push_back(createSimpleEvent(2222L, 44)); + + pullSuccess = true; + + EXPECT_FALSE(puller.Pull(eventTimeNs, &dataHolder)); ASSERT_EQ(0, dataHolder.size()); } diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp index 12839e6d1fbe..cc5f45922d45 100644 --- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp @@ -138,11 +138,12 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) { sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs); data->clear(); - data->push_back(makeLogEvent(tagId, bucketStartTimeNs + 10, 3, "some value", 11)); + data->push_back(makeLogEvent(tagId, eventTimeNs + 10, 3, "some value", 11)); return true; })); @@ -311,15 +312,15 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPulled) { sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) .WillOnce(Return(false)) - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back( - CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 2)); - return true; - })); + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs); + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs, 2)); + return true; + })); GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, @@ -389,7 +390,8 @@ TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) { sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(false)); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) + .WillOnce(Return(false)); GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, @@ -435,14 +437,16 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) { new EventMatcherWizard({new SimpleLogMatchingTracker( atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + int64_t conditionChangeNs = bucketStartTimeNs + 8; + sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, conditionChangeNs, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 100)); + data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs + 10, 100)); return true; })); @@ -451,7 +455,7 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) { bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); - gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8); + gaugeProducer.onConditionChanged(true, conditionChangeNs); ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(100, gaugeProducer.mCurrentSlicedBucket->begin() ->second.front() @@ -519,14 +523,16 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) { return ConditionState::kTrue; })); + int64_t sliceConditionChangeNs = bucketStartTimeNs + 8; + sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, sliceConditionChangeNs, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { data->clear(); - data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 10, 1000, 100)); + data->push_back(CreateTwoValueLogEvent(tagId, eventTimeNs + 10, 1000, 100)); return true; })); @@ -535,7 +541,7 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) { bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); - gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8); + gaugeProducer.onSlicedConditionMayChange(true, sliceConditionChangeNs); ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); const auto& key = gaugeProducer.mCurrentSlicedBucket->begin()->first; @@ -560,7 +566,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) { sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(false)); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) + .WillOnce(Return(false)); GaugeMetric metric; metric.set_id(metricId); @@ -658,17 +665,19 @@ TEST(GaugeMetricProducerTest, TestPullOnTrigger) { atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10); data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 4)); + data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs, 4)); return true; })) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20); data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20, 5)); + data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs, 5)); return true; })) .WillOnce(Return(true)); @@ -727,23 +736,26 @@ TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) { atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 3, 3, 4)); - return true; - })) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3); + data->clear(); + data->push_back(CreateTwoValueLogEvent(tagId, eventTimeNs, 3, 4)); + return true; + })) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10); data->clear(); - data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 10, 4, 5)); + data->push_back(CreateTwoValueLogEvent(tagId, eventTimeNs, 4, 5)); return true; })) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20); data->clear(); - data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 20, 4, 6)); + data->push_back(CreateTwoValueLogEvent(tagId, eventTimeNs, 4, 6)); return true; })) .WillOnce(Return(true)); @@ -801,14 +813,14 @@ TEST(GaugeMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) { atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 3, _, _)) // Bucket start. - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 10)); - return true; - })); + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs, 10)); + return true; + })); int triggerId = 5; GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp index be1b9ebb557c..474aa2234837 100644 --- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp @@ -278,13 +278,13 @@ TEST(ValueMetricProducerTest, TestFirstBucket) { TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3)); - return true; - })); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, + vector<std::shared_ptr<LogEvent>>* data, bool) { + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3)); + return true; + })); sp<ValueMetricProducer> valueProducer = ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); @@ -352,18 +352,20 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPartialBucketCreated) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 2; - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // Initialize bucket. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1)); return true; })) // Partial bucket. - .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&, - vector<std::shared_ptr<LogEvent>>* data, - bool) { + .WillOnce(Invoke([partialBucketSplitTimeNs]( + int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs); data->clear(); data->push_back( CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs + 8, 5)); @@ -416,13 +418,13 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) { sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 3, 3)); - return true; - })); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, + vector<std::shared_ptr<LogEvent>>* data, bool) { + data->clear(); + data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 3, 3)); + return true; + })); sp<ValueMetricProducer> valueProducer = new ValueMetricProducer( kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex, @@ -487,7 +489,8 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) { metric.set_use_absolute_value_on_reset(true); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(true)); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) + .WillOnce(Return(true)); sp<ValueMetricProducer> valueProducer = ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); @@ -546,7 +549,8 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) { TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(false)); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) + .WillOnce(Return(false)); sp<ValueMetricProducer> valueProducer = ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); @@ -601,21 +605,24 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) { sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8); // First condition change. data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100)); return true; })) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1); // Second condition change. data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 130)); return true; })) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucket3StartTimeNs + 1); // Third condition change. data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 180)); return true; @@ -745,11 +752,12 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValue) { int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 150; EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) .WillOnce(Return(true)) - .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&, - vector<std::shared_ptr<LogEvent>>* data, - bool) { + .WillOnce(Invoke([partialBucketSplitTimeNs]( + int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 120)); return true; @@ -803,7 +811,8 @@ TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) { sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(true)); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) + .WillOnce(Return(true)); ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); @@ -825,15 +834,18 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValueWhileConditionFalse ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 1); // Condition change to true time. data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100)); return true; })) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, + bucket2StartTimeNs - 100); // Condition change to false time. data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs - 100, 120)); return true; @@ -1049,7 +1061,8 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) { TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(true)); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) + .WillOnce(Return(true)); sp<ValueMetricProducer> valueProducer = ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); @@ -1119,17 +1132,19 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) { ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // condition becomes true - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8); // First condition change. data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100)); return true; })) // condition becomes false - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1); // Second condition change. data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120)); return true; @@ -1179,24 +1194,27 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) { ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // condition becomes true - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100)); return true; })) // condition becomes false - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120)); return true; })) // condition becomes true again - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 25); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 25, 130)); return true; @@ -1625,13 +1643,13 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) { metric.set_use_zero_default_base(true); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3)); - return true; - })); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, + vector<std::shared_ptr<LogEvent>>* data, bool) { + data->clear(); + data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3)); + return true; + })); sp<ValueMetricProducer> valueProducer = ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); @@ -1701,13 +1719,13 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) { metric.set_use_zero_default_base(true); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3)); - return true; - })); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, + vector<std::shared_ptr<LogEvent>>* data, bool) { + data->clear(); + data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3)); + return true; + })); sp<ValueMetricProducer> valueProducer = ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); @@ -1806,13 +1824,13 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) { metric.mutable_dimensions_in_what()->add_child()->set_field(1); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3)); - return true; - })); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, + vector<std::shared_ptr<LogEvent>>* data, bool) { + data->clear(); + data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3)); + return true; + })); sp<ValueMetricProducer> valueProducer = ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); @@ -1909,8 +1927,8 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfB sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); // Used by onConditionChanged. - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 8, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, vector<std::shared_ptr<LogEvent>>* data, bool) { data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100)); @@ -1942,9 +1960,10 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) { ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8); // Condition change to true. data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100)); return true; @@ -1979,15 +1998,17 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) { ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 50)); - return false; - })) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs); + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 50)); + return false; + })) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 1); // Condition change to false. data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100)); return true; @@ -2019,8 +2040,8 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) { metric.set_max_pull_delay_sec(0); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 1, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, vector<std::shared_ptr<LogEvent>>* data, bool) { data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 120)); @@ -2067,8 +2088,8 @@ TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) { ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 1, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, vector<std::shared_ptr<LogEvent>>* data, bool) { data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100)); @@ -2100,12 +2121,13 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // First onConditionChanged .WillOnce(Return(false)) // Second onConditionChanged - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130)); return true; @@ -2177,9 +2199,9 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenGuardRailHit) { metric.set_condition(StringToId("SCREEN_ON")); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 2, _, _)) // First onConditionChanged - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, vector<std::shared_ptr<LogEvent>>* data, bool) { for (int i = 0; i < 2000; i++) { data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, i)); @@ -2234,17 +2256,19 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed) ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // First onConditionChanged - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 2); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 120)); return true; })) // Second onConditionChanged - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130)); return true; @@ -2312,17 +2336,19 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) { ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // First onConditionChanged - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 2); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 120)); return true; })) // Second onConditionChanged - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130)); return true; @@ -2384,14 +2410,14 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) { TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) // Start bucket. - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3)); - return true; - })); + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, + vector<std::shared_ptr<LogEvent>>* data, bool) { + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3)); + return true; + })); sp<ValueMetricProducer> valueProducer = ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); @@ -2417,19 +2443,21 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) { ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // First onConditionChanged - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3)); - return true; - })) - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - return true; - })); + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10); + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3)); + return true; + })) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10); + data->clear(); + return true; + })); sp<ValueMetricProducer> valueProducer = ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); @@ -2457,26 +2485,29 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) { ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // First onConditionChanged - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1)); - return true; - })) - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 2)); - return true; - })) - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 5)); - return true; - })); + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10); + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1)); + return true; + })) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 11); + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 2)); + return true; + })) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 12); + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 5)); + return true; + })); sp<ValueMetricProducer> valueProducer = ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); @@ -2517,14 +2548,14 @@ TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) { metric.set_condition(StringToId("SCREEN_ON")); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 10, _, _)) // First onConditionChanged - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1)); - return true; - })); + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, + vector<std::shared_ptr<LogEvent>>* data, bool) { + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1)); + return true; + })); sp<ValueMetricProducer> valueProducer = ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); @@ -2559,18 +2590,20 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestFullBucketResetWhenLastBucketI sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); int64_t partialBucketSplitTimeNs = bucketStartTimeNs + bucketSizeNs / 2; - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // Initialization. - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1)); - return true; - })) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs); + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1)); + return true; + })) // notifyAppUpgrade. - .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&, - vector<std::shared_ptr<LogEvent>>* data, - bool) { + .WillOnce(Invoke([partialBucketSplitTimeNs]( + int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 10)); return true; @@ -2609,17 +2642,19 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestFullBucketResetWhenLastBucketI TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) { ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // Second onConditionChanged. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 5)); return true; })) // Third onConditionChanged. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucket3StartTimeNs + 10); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 10, 7)); return true; @@ -2678,14 +2713,14 @@ TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) // Initialization. - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1)); - return true; - })); + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, + vector<std::shared_ptr<LogEvent>>* data, bool) { + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1)); + return true; + })); sp<ValueMetricProducer> valueProducer = ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); @@ -2708,18 +2743,20 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestBucketBoundariesOnPartialBucke int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 2; sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // Initialization. - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1)); - return true; - })) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs); + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1)); + return true; + })) // notifyAppUpgrade. - .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&, - vector<std::shared_ptr<LogEvent>>* data, - bool) { + .WillOnce(Invoke([partialBucketSplitTimeNs]( + int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 10)); return true; @@ -2746,21 +2783,23 @@ TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) { ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // First on condition changed. - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1)); - return true; - })) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8); + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1)); + return true; + })) // Second on condition changed. - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3)); - return true; - })); + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10); + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3)); + return true; + })); sp<ValueMetricProducer> valueProducer = ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); @@ -2788,28 +2827,31 @@ TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) { ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // First condition change. - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1)); - return true; - })) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10); + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1)); + return true; + })) // 2nd condition change. - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1)); - return true; - })) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 8); + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1)); + return true; + })) // 3rd condition change. - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1)); - return true; - })); + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10); + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1)); + return true; + })); sp<ValueMetricProducer> valueProducer = ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); @@ -2848,9 +2890,9 @@ TEST(ValueMetricProducerTest, TestPullNeededFastDump) { EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) // Initial pull. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, vector<std::shared_ptr<LogEvent>>* data, bool) { data->clear(); data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1)); @@ -2886,9 +2928,9 @@ TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) { EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) // Initial pull. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, vector<std::shared_ptr<LogEvent>>* data, bool) { data->clear(); data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1)); @@ -2930,16 +2972,18 @@ TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) { EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // Initial pull. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs); data->clear(); data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1)); return true; })) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10); data->clear(); data->push_back( CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 10, tagId, 3, 3)); @@ -2984,17 +3028,19 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges metric.set_use_diff(false); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // condition becomes true - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10)); return true; })) // condition becomes false - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 20)); return true; @@ -3032,9 +3078,9 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) { metric.set_use_diff(false); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 8, _, _)) // condition becomes true - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, vector<std::shared_ptr<LogEvent>>* data, bool) { data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10)); @@ -3083,10 +3129,11 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) { metric.set_use_diff(false); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // condition becomes true - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10)); return true; @@ -3122,9 +3169,9 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenDumpReportRequeste ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 20, _, _)) // Condition change to true. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, vector<std::shared_ptr<LogEvent>>* data, bool) { data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20, 10)); @@ -3167,9 +3214,9 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionEventWron ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 50, _, _)) // Condition change to true. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, vector<std::shared_ptr<LogEvent>>* data, bool) { data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10)); @@ -3220,17 +3267,19 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenAccumulateEventWro ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // Condition change to true. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10)); return true; })) // Dump report requested. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 100); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 100, 15)); return true; @@ -3283,17 +3332,19 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionUnknown) ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // Condition change to true. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10)); return true; })) // Dump report requested. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10000); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 100, 15)); return true; @@ -3337,10 +3388,11 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenPullFailed) { ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // Condition change to true. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10)); return true; @@ -3385,17 +3437,19 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenMultipleBucketsSki ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // Condition change to true. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10)); return true; })) // Dump report requested. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucket4StartTimeNs + 10); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1000, 15)); return true; @@ -3441,17 +3495,19 @@ TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) { metric.set_min_bucket_size_nanos(10000000000); // 10 seconds sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // Condition change to true. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10)); return true; })) // Dump report requested. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 9000000); data->clear(); data->push_back( CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 9000000, 15)); @@ -3494,9 +3550,9 @@ TEST(ValueMetricProducerTest_BucketDrop, TestMultipleBucketDropEvents) { ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 10, _, _)) // Condition change to true. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t, vector<std::shared_ptr<LogEvent>>* data, bool) { data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10)); @@ -3545,10 +3601,11 @@ TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) { ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // First condition change event. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10); for (int i = 0; i < 2000; i++) { data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, i)); } @@ -3563,8 +3620,9 @@ TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) { .WillOnce(Return(false)) .WillOnce(Return(false)) .WillOnce(Return(false)) - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 220); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 220, 10)); return true; @@ -3662,38 +3720,43 @@ TEST(ValueMetricProducerTest, TestSlicedState) { // Set up ValueMetricProducer. ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE"); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // ValueMetricProducer initialized. - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3)); - return true; - })) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs); + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3)); + return true; + })) // Screen state change to ON. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 5); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5, 5)); return true; })) // Screen state change to OFF. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 9)); return true; })) // Screen state change to ON. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 15); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 15, 21)); return true; })) // Dump report requested. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 30)); return true; @@ -3818,38 +3881,41 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) { // Set up ValueMetricProducer. ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF"); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // ValueMetricProducer initialized. - .WillOnce(Invoke( - [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) { - data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3)); - return true; - })) - // Screen state change to ON. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs); data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5, 5)); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3)); return true; })) - // Screen state change to VR. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + // Screen state change to ON. + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 5); data->clear(); - data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 9)); + data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5, 5)); return true; })) + // Screen state change to VR has no pull because it is in the same + // state group as ON. + + // Screen state change to ON has no pull because it is in the same + // state group as VR. + // Screen state change to OFF. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 15); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 15, 21)); return true; })) // Dump report requested. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50); data->clear(); data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 30)); return true; @@ -3901,23 +3967,33 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) { EXPECT_EQ(true, it->second[0].hasValue); EXPECT_EQ(2, it->second[0].value.long_value); - // Bucket status after screen state change ON->VR (also ON). + // Bucket status after screen state change ON->VR. + // Both ON and VR are in the same state group, so the base should not change. screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 10, android::view::DisplayStateEnum::DISPLAY_STATE_VR); StateManager::getInstance().onLogEvent(*screenEvent); - ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size()); + ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); // Base for dimension key {} it = valueProducer->mCurrentSlicedBucket.begin(); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); EXPECT_EQ(true, itBase->second[0].hasBase); - EXPECT_EQ(9, itBase->second[0].base.long_value); - // Value for dimension, state key {{}, ON GROUP} - EXPECT_EQ(screenOnGroup.group_id(), - it->first.getStateValuesKey().getValues()[0].mValue.long_value); + EXPECT_EQ(5, itBase->second[0].base.long_value); + // Value for dimension, state key {{}, kStateUnknown} EXPECT_EQ(true, it->second[0].hasValue); - EXPECT_EQ(4, it->second[0].value.long_value); + EXPECT_EQ(2, it->second[0].value.long_value); + + // Bucket status after screen state change VR->ON. + // Both ON and VR are in the same state group, so the base should not change. + screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 12, + android::view::DisplayStateEnum::DISPLAY_STATE_ON); + StateManager::getInstance().onLogEvent(*screenEvent); + EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); + // Base for dimension key {} + it = valueProducer->mCurrentSlicedBucket.begin(); + itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); + EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_EQ(5, itBase->second[0].base.long_value); // Value for dimension, state key {{}, kStateUnknown} - it++; EXPECT_EQ(true, it->second[0].hasValue); EXPECT_EQ(2, it->second[0].value.long_value); @@ -3990,18 +4066,20 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) { *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */}); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) // ValueMetricProducer initialized. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs); data->clear(); data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 2 /*uid*/, 7)); data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1 /*uid*/, 3)); return true; })) // Uid 1 process state change from kStateUnknown -> Foreground - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20); data->clear(); data->push_back( CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 20, 1 /*uid*/, 6)); @@ -4012,8 +4090,9 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) { return true; })) // Uid 2 process state change from kStateUnknown -> Background - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 40); data->clear(); data->push_back( CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 40, 2 /*uid*/, 9)); @@ -4024,8 +4103,9 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) { return true; })) // Uid 1 process state change from Foreground -> Background - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 20); data->clear(); data->push_back( CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 20, 1 /*uid*/, 13)); @@ -4036,8 +4116,9 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) { return true; })) // Uid 1 process state change from Background -> Foreground - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 40); data->clear(); data->push_back( CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 40, 1 /*uid*/, 17)); @@ -4048,8 +4129,9 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) { return true; })) // Dump report pull. - .WillOnce(Invoke([](int tagId, const ConfigKey&, + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 50); data->clear(); data->push_back( CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 50, 2 /*uid*/, 20)); diff --git a/cmds/statsd/tests/metrics/metrics_test_helper.h b/cmds/statsd/tests/metrics/metrics_test_helper.h index 46ef0f613bbe..eeb38a4644fd 100644 --- a/cmds/statsd/tests/metrics/metrics_test_helper.h +++ b/cmds/statsd/tests/metrics/metrics_test_helper.h @@ -38,10 +38,11 @@ public: int64_t nextPulltimeNs, int64_t intervalNs)); MOCK_METHOD3(UnRegisterReceiver, void(int tagId, const ConfigKey& key, wp<PullDataReceiver> receiver)); - MOCK_METHOD4(Pull, bool(const int pullCode, const ConfigKey& key, - vector<std::shared_ptr<LogEvent>>* data, bool useUids)); - MOCK_METHOD4(Pull, bool(const int pullCode, const vector<int32_t>& uids, + MOCK_METHOD5(Pull, bool(const int pullCode, const ConfigKey& key, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data, bool useUids)); + MOCK_METHOD5(Pull, + bool(const int pullCode, const vector<int32_t>& uids, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool useUids)); MOCK_METHOD2(RegisterPullUidProvider, void(const ConfigKey& configKey, wp<PullUidProvider> provider)); MOCK_METHOD2(UnregisterPullUidProvider, diff --git a/cmds/statsd/tests/shell/ShellSubscriber_test.cpp b/cmds/statsd/tests/shell/ShellSubscriber_test.cpp index 363fcb4bf193..e384b6ac7c84 100644 --- a/cmds/statsd/tests/shell/ShellSubscriber_test.cpp +++ b/cmds/statsd/tests/shell/ShellSubscriber_test.cpp @@ -190,8 +190,8 @@ TEST(ShellSubscriberTest, testPulledSubscription) { sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); const vector<int32_t> uids = {AID_SYSTEM}; - EXPECT_CALL(*pullerManager, Pull(10016, uids, _, _)) - .WillRepeatedly(Invoke([](int tagId, const vector<int32_t>&, + EXPECT_CALL(*pullerManager, Pull(10016, uids, _, _, _)) + .WillRepeatedly(Invoke([](int tagId, const vector<int32_t>&, const int64_t, vector<std::shared_ptr<LogEvent>>* data, bool) { data->clear(); data->push_back(makeCpuActiveTimeAtom(/*uid=*/kUid1, /*timeMillis=*/kCpuTime1)); diff --git a/cmds/statsd/tests/state/StateTracker_test.cpp b/cmds/statsd/tests/state/StateTracker_test.cpp index 13e8f5c343f2..530ac5e01f3e 100644 --- a/cmds/statsd/tests/state/StateTracker_test.cpp +++ b/cmds/statsd/tests/state/StateTracker_test.cpp @@ -50,8 +50,9 @@ public: std::vector<Update> updates; void onStateChanged(const int64_t eventTimeNs, const int32_t atomId, - const HashableDimensionKey& primaryKey, int oldState, int newState) { - updates.emplace_back(primaryKey, newState); + const HashableDimensionKey& primaryKey, const FieldValue& oldState, + const FieldValue& newState) { + updates.emplace_back(primaryKey, newState.mValue.int_value); } }; diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp index fae56f09c1df..582df0c1a2a3 100644 --- a/cmds/statsd/tests/statsd_test_util.cpp +++ b/cmds/statsd/tests/statsd_test_util.cpp @@ -169,7 +169,6 @@ AtomMatcher CreateScreenStateChangedAtomMatcher( return atom_matcher; } - AtomMatcher CreateScreenTurnedOnAtomMatcher() { return CreateScreenStateChangedAtomMatcher("ScreenTurnedOn", android::view::DisplayStateEnum::DISPLAY_STATE_ON); @@ -335,22 +334,46 @@ State CreateScreenStateWithOnOffMap(int64_t screenOnId, int64_t screenOffId) { 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(2); - group.add_value(5); - group.add_value(6); + 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(0); - group.add_value(1); - group.add_value(3); - group.add_value(4); + 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; } @@ -361,6 +384,13 @@ StateMap CreateScreenStateOnOffMap(int64_t screenOnId, int64_t 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()); @@ -1339,7 +1369,7 @@ Status FakeSubsystemSleepCallback::onPullAtom(int atomTag, // 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_write(event); + AStatsEvent_release(event); } resultReceiver->pullFinished(atomTag, /*success=*/true, parcels); return Status::ok(); diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h index dc012c5381eb..6a5d5da2895c 100644 --- a/cmds/statsd/tests/statsd_test_util.h +++ b/cmds/statsd/tests/statsd_test_util.h @@ -149,17 +149,30 @@ State CreateUidProcessState(); // Create State proto for overlay state atom. State CreateOverlayState(); +// Create State proto for screen state atom with on/off map. State CreateScreenStateWithOnOffMap(int64_t screenOnId, int64_t screenOffId); +// Create State proto for screen state atom with simple on/off map. +State CreateScreenStateWithSimpleOnOffMap(int64_t screenOnId, int64_t screenOffId); + // Create StateGroup proto for ScreenState ON group StateMap_StateGroup CreateScreenStateOnGroup(int64_t screenOnId); // Create StateGroup proto for ScreenState OFF group StateMap_StateGroup CreateScreenStateOffGroup(int64_t screenOffId); +// Create StateGroup proto for simple ScreenState ON group +StateMap_StateGroup CreateScreenStateSimpleOnGroup(int64_t screenOnId); + +// Create StateGroup proto for simple ScreenState OFF group +StateMap_StateGroup CreateScreenStateSimpleOffGroup(int64_t screenOffId); + // Create StateMap proto for ScreenState ON/OFF map StateMap CreateScreenStateOnOffMap(int64_t screenOnId, int64_t screenOffId); +// Create StateMap proto for simple ScreenState ON/OFF map +StateMap CreateScreenStateSimpleOnOffMap(int64_t screenOnId, int64_t screenOffId); + // Add a predicate to the predicate combination. void addPredicateToPredicateCombination(const Predicate& predicate, Predicate* combination); diff --git a/cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java b/cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java index c35f7fc3fcc8..3b14be7327f7 100644 --- a/cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java +++ b/cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java @@ -16,6 +16,7 @@ package com.android.commands.uiautomator; +import android.accessibilityservice.AccessibilityServiceInfo; import android.app.UiAutomation; import android.graphics.Point; import android.hardware.display.DisplayManagerGlobal; @@ -61,11 +62,14 @@ public class DumpCommand extends Command { public void run(String[] args) { File dumpFile = DEFAULT_DUMP_FILE; boolean verboseMode = true; + boolean allWindows = false; for (String arg : args) { if (arg.equals("--compressed")) verboseMode = false; - else if (!arg.startsWith("-")) { + else if (arg.equals("--windows")) { + allWindows = true; + } else if (!arg.startsWith("-")) { dumpFile = new File(arg); } } @@ -85,18 +89,28 @@ public class DumpCommand extends Command { try { UiAutomation uiAutomation = automationWrapper.getUiAutomation(); uiAutomation.waitForIdle(1000, 1000 * 10); - AccessibilityNodeInfo info = uiAutomation.getRootInActiveWindow(); - if (info == null) { - System.err.println("ERROR: null root node returned by UiTestAutomationBridge."); - return; - } + if (allWindows) { + AccessibilityServiceInfo info = uiAutomation.getServiceInfo(); + info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS; + uiAutomation.setServiceInfo(info); + AccessibilityNodeInfoDumper.dumpWindowsToFile( + uiAutomation.getWindowsOnAllDisplays(), dumpFile, + DisplayManagerGlobal.getInstance()); + } else { + AccessibilityNodeInfo info = uiAutomation.getRootInActiveWindow(); + if (info == null) { + System.err.println("ERROR: null root node returned by UiTestAutomationBridge."); + return; + } - Display display = - DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); - int rotation = display.getRotation(); - Point size = new Point(); - display.getSize(size); - AccessibilityNodeInfoDumper.dumpWindowToFile(info, dumpFile, rotation, size.x, size.y); + Display display = + DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); + int rotation = display.getRotation(); + Point size = new Point(); + display.getSize(size); + AccessibilityNodeInfoDumper.dumpWindowToFile(info, dumpFile, rotation, size.x, + size.y); + } } catch (TimeoutException re) { System.err.println("ERROR: could not get idle state."); return; diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java index 63c51e84d74a..ab198b319e27 100644 --- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java +++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java @@ -16,11 +16,17 @@ package com.android.uiautomator.core; +import android.graphics.Point; +import android.graphics.Rect; +import android.hardware.display.DisplayManagerGlobal; import android.os.Environment; import android.os.SystemClock; import android.util.Log; +import android.util.SparseArray; import android.util.Xml; +import android.view.Display; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityWindowInfo; import org.xmlpull.v1.XmlSerializer; @@ -28,6 +34,7 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.StringWriter; +import java.util.List; /** * @@ -98,6 +105,95 @@ public class AccessibilityNodeInfoDumper { Log.w(LOGTAG, "Fetch time: " + (endTime - startTime) + "ms"); } + /** + * Using {@link AccessibilityWindowInfo} this method will dump some window information and + * then walk the layout hierarchy of it's + * and generates an xml dump to the location specified by <code>dumpFile</code> + * @param allWindows All windows indexed by display-id. + * @param dumpFile The file to dump to. + */ + public static void dumpWindowsToFile(SparseArray<List<AccessibilityWindowInfo>> allWindows, + File dumpFile, DisplayManagerGlobal displayManager) { + if (allWindows.size() == 0) { + return; + } + final long startTime = SystemClock.uptimeMillis(); + try { + FileWriter writer = new FileWriter(dumpFile); + XmlSerializer serializer = Xml.newSerializer(); + StringWriter stringWriter = new StringWriter(); + serializer.setOutput(stringWriter); + serializer.startDocument("UTF-8", true); + serializer.startTag("", "displays"); + for (int d = 0, nd = allWindows.size(); d < nd; ++d) { + int displayId = allWindows.keyAt(d); + Display display = displayManager.getRealDisplay(displayId); + if (display == null) { + continue; + } + final List<AccessibilityWindowInfo> windows = allWindows.valueAt(d); + if (windows.isEmpty()) { + continue; + } + serializer.startTag("", "display"); + serializer.attribute("", "id", Integer.toString(displayId)); + int rotation = display.getRotation(); + Point size = new Point(); + display.getSize(size); + for (int i = 0, n = windows.size(); i < n; ++i) { + dumpWindowRec(windows.get(i), serializer, i, size.x, size.y, rotation); + } + serializer.endTag("", "display"); + } + serializer.endTag("", "displays"); + serializer.endDocument(); + writer.write(stringWriter.toString()); + writer.close(); + } catch (IOException e) { + Log.e(LOGTAG, "failed to dump window to file", e); + } + final long endTime = SystemClock.uptimeMillis(); + Log.w(LOGTAG, "Fetch time: " + (endTime - startTime) + "ms"); + } + + private static void dumpWindowRec(AccessibilityWindowInfo winfo, XmlSerializer serializer, + int index, int width, int height, int rotation) throws IOException { + serializer.startTag("", "window"); + serializer.attribute("", "index", Integer.toString(index)); + final CharSequence title = winfo.getTitle(); + serializer.attribute("", "title", title != null ? title.toString() : ""); + final Rect tmpBounds = new Rect(); + winfo.getBoundsInScreen(tmpBounds); + serializer.attribute("", "bounds", tmpBounds.toShortString()); + serializer.attribute("", "active", Boolean.toString(winfo.isActive())); + serializer.attribute("", "focused", Boolean.toString(winfo.isFocused())); + serializer.attribute("", "accessibility-focused", + Boolean.toString(winfo.isAccessibilityFocused())); + serializer.attribute("", "id", Integer.toString(winfo.getId())); + serializer.attribute("", "layer", Integer.toString(winfo.getLayer())); + serializer.attribute("", "type", AccessibilityWindowInfo.typeToString(winfo.getType())); + int count = winfo.getChildCount(); + for (int i = 0; i < count; ++i) { + AccessibilityWindowInfo child = winfo.getChild(i); + if (child == null) { + Log.i(LOGTAG, String.format("Null window child %d/%d, parent: %s", i, count, + winfo.getTitle())); + continue; + } + dumpWindowRec(child, serializer, i, width, height, rotation); + child.recycle(); + } + AccessibilityNodeInfo root = winfo.getRoot(); + if (root != null) { + serializer.startTag("", "hierarchy"); + serializer.attribute("", "rotation", Integer.toString(rotation)); + dumpNodeRec(root, serializer, 0, width, height); + root.recycle(); + serializer.endTag("", "hierarchy"); + } + serializer.endTag("", "window"); + } + private static void dumpNodeRec(AccessibilityNodeInfo node, XmlSerializer serializer,int index, int width, int height) throws IOException { serializer.startTag("", "node"); |