diff options
79 files changed, 1646 insertions, 3675 deletions
diff --git a/Android.bp b/Android.bp index b2ed0de2f2e9..af2f112bb6ae 100644 --- a/Android.bp +++ b/Android.bp @@ -26,47 +26,164 @@ // READ ME: ######################################################## filegroup { - name: "framework-defaults-java-srcs", + name: "framework-core-sources", srcs: [ - // java sources under this directory "core/java/**/*.java", + "core/java/**/*.aidl", + ], + path: "core/java", +} + +filegroup { + name: "framework-drm-sources", + srcs: [ "drm/java/**/*.java", + ], + path: "drm/java", +} + +filegroup { + name: "framework-graphics-sources", + srcs: [ "graphics/java/**/*.java", + "graphics/java/**/*.aidl", + ], + path: "graphics/java", +} + +filegroup { + name: "framework-keystore-sources", + srcs: [ "keystore/java/**/*.java", + "keystore/java/**/*.aidl", + ], + path: "keystore/java", +} + +filegroup { + name: "framework-location-sources", + srcs: [ "location/java/**/*.java", + "location/java/**/*.aidl", + ], + path: "location/java", +} + +filegroup { + name: "framework-lowpan-sources", + srcs: [ "lowpan/java/**/*.java", + "lowpan/java/**/*.aidl", + ], + path: "lowpan/java", +} + +filegroup { + name: "framework-media-sources", + srcs: [ "media/java/**/*.java", + "media/java/**/*.aidl", + ], + path: "media/java", +} + +filegroup { + name: "framework-mca-effect-sources", + srcs: [ "media/mca/effect/java/**/*.java", + ], + path: "media/mca/effect/java", +} + +filegroup { + name: "framework-mca-filterfw-sources", + srcs: [ "media/mca/filterfw/java/**/*.java", + ], + path: "media/mca/filterfw/java", +} + +filegroup { + name: "framework-mca-filterpacks-sources", + srcs: [ "media/mca/filterpacks/java/**/*.java", + ], + path: "media/mca/filterpacks/java", +} + +filegroup { + name: "framework-opengl-sources", + srcs: [ "opengl/java/**/*.java", + ], + path: "opengl/java", +} + +filegroup { + name: "framework-rs-sources", + srcs: [ "rs/java/**/*.java", + ], + path: "rs/java", +} + +filegroup { + name: "framework-sax-sources", + srcs: [ "sax/java/**/*.java", + ], + path: "sax/java", +} + +filegroup { + name: "framework-telecomm-sources", + srcs: [ "telecomm/java/**/*.java", + "telecomm/java/**/*.aidl", + ], + path: "telecomm/java", +} + +filegroup { + name: "framework-telephony-sources", + srcs: [ "telephony/java/**/*.java", + "telephony/java/**/*.aidl", + ], + path: "telephony/java", +} + +filegroup { + name: "framework-wifi-sources", + srcs: [ "wifi/java/**/*.java", + "wifi/java/**/*.aidl", ], + path: "wifi/java", } -// TODO(b/70046217): make these as filegroups where the base directory for aidl files -// is given as 'path'. Eliminate the need for aidl_local_include_dirs. framework_srcs = [ - // aidl under this directory - // b/70046217#comment15 These MUST come after all java srcs. - // TODO(b/70046217) remove the above requirement - "core/java/**/*.aidl", - "graphics/java/**/*.aidl", - "keystore/java/**/*.aidl", - "location/java/**/*.aidl", - "lowpan/java/**/*.aidl", - "media/java/**/*.aidl", - "packages/services/PacProcessor/**/*.aidl", - "packages/services/Proxy/**/*.aidl", - "telecomm/java/**/*.aidl", - "telephony/java/**/*.aidl", - "wifi/java/**/*.aidl", - - // aidl from external directories + // Java/AIDL sources under frameworks/base + ":framework-core-sources", + ":framework-drm-sources", + ":framework-graphics-sources", + ":framework-keystore-sources", + ":framework-location-sources", + ":framework-lowpan-sources", + ":framework-media-sources", + ":framework-mca-effect-sources", + ":framework-mca-filterfw-sources", + ":framework-mca-filterpacks-sources", + ":framework-opengl-sources", + ":framework-rs-sources", + ":framework-sax-sources", + ":framework-telecomm-sources", + ":framework-telephony-sources", + ":framework-wifi-sources", + ":PacProcessor-aidl-sources", + ":ProxyHandler-aidl-sources", + + // AIDL sources from external directories ":dumpstate_aidl", ":gatekeeper_aidl", ":gsiservice_aidl", @@ -88,47 +205,28 @@ framework_srcs = [ ":framework-statslog-gen", ] -framework_aidl_local_include_dirs = [ - "core/java", - "drm/java", - "graphics/java", - "keystore/java", - "location/java", - "lowpan/java", - "media/java", - "media/apex/java", - "media/mca/effect/java", - "media/mca/filterfw/java", - "media/mca/filterpacks/java", - "opengl/java", - "rs/java", - "sax/java", - "telecomm/java", - "telephony/java", - "wifi/java", -] - -framework_aidl_external_include_dirs = [ - "frameworks/av/camera/aidl", - "frameworks/av/media/libaudioclient/aidl", - "frameworks/native/aidl/binder", - "frameworks/native/aidl/gui", - "frameworks/native/cmds/dumpstate/binder", - "frameworks/native/libs/incidentcompanion/binder", - "system/bt/binder", - "system/core/gatekeeperd/binder", - "system/core/storaged/binder", - "system/gsid/aidl", - "system/security/keystore/binder", - "system/update_engine/binder_bindings", - "system/vold/binder", -] - java_defaults { name: "framework-aidl-export-defaults", - aidl: { - export_include_dirs: framework_aidl_local_include_dirs, + export_include_dirs: [ + "core/java", + "drm/java", + "graphics/java", + "keystore/java", + "location/java", + "lowpan/java", + "media/java", + "media/apex/java", + "media/mca/effect/java", + "media/mca/filterfw/java", + "media/mca/filterpacks/java", + "opengl/java", + "rs/java", + "sax/java", + "telecomm/java", + "telephony/java", + "wifi/java", + ], }, } @@ -137,13 +235,15 @@ java_defaults { defaults: ["framework-aidl-export-defaults"], installable: true, - srcs: [ - ":framework-defaults-java-srcs", - ] + framework_srcs, + srcs: framework_srcs, aidl: { - local_include_dirs: framework_aidl_local_include_dirs, - include_dirs: framework_aidl_external_include_dirs, + // TODO(b/70046217) remove this by moving the AIDL files into frameworks/base + // so that they are referenced via framework-core-sources + include_dirs: [ + "frameworks/native/aidl/binder", + "frameworks/native/aidl/gui", + ], generate_get_transaction_name: true, }, @@ -793,7 +893,6 @@ stubs_defaults { ":jobscheduler-framework-source", ], srcs_lib: "framework-minus-apex", - srcs_lib_whitelist_dirs: frameworks_base_subdirs, srcs_lib_whitelist_pkgs: packages_to_document, libs: framework_docs_only_libs, local_sourcepaths: frameworks_base_subdirs, @@ -851,7 +950,6 @@ stubs_defaults { ":jobscheduler-framework-source", ], srcs_lib: "framework-minus-apex", - srcs_lib_whitelist_dirs: frameworks_base_subdirs, srcs_lib_whitelist_pkgs: packages_to_document, local_sourcepaths: frameworks_base_subdirs, installable: false, @@ -1172,8 +1270,7 @@ droidstubs { droidstubs { name: "hiddenapi-mappings", defaults: ["metalava-api-stubs-default"], - srcs: [ - ":framework-defaults-java-srcs", + srcs: framework_srcs + [ ":non_openjdk_java_files", ":openjdk_java_files", ":opt-telephony-common-srcs", @@ -1313,8 +1410,6 @@ filegroup { aidl_mapping { name: "framework-aidl-mappings", srcs: framework_srcs, - local_include_dirs: framework_aidl_local_include_dirs, - include_dirs: framework_aidl_external_include_dirs, output: "framework-aidl-mappings.txt", } diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp index 6df0a8e14f6a..19fa64073183 100644 --- a/cmds/statsd/Android.bp +++ b/cmds/statsd/Android.bp @@ -129,17 +129,12 @@ cc_defaults { "libservices", "libprotoutil", "libstatslog", - "libhardware", - "libhardware_legacy", "libhidlbase", - "libhidltransport", - "libhwbinder", "android.frameworks.stats@1.0", "android.hardware.health@2.0", "android.hardware.power@1.0", "android.hardware.power@1.1", "android.hardware.power.stats@1.0", - "libpackagelistparser", "libsysutils", "libcutils", ], @@ -253,9 +248,6 @@ cc_test { "tests/e2e/GaugeMetric_e2e_push_test.cpp", "tests/e2e/GaugeMetric_e2e_pull_test.cpp", "tests/e2e/ValueMetric_pull_e2e_test.cpp", - "tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp", - "tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp", - "tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp", "tests/e2e/Anomaly_count_e2e_test.cpp", "tests/e2e/Anomaly_duration_sum_e2e_test.cpp", "tests/e2e/ConfigTtl_e2e_test.cpp", diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.cpp b/cmds/statsd/src/condition/CombinationConditionTracker.cpp index 60a4b236df11..52a1269798ca 100644 --- a/cmds/statsd/src/condition/CombinationConditionTracker.cpp +++ b/cmds/statsd/src/condition/CombinationConditionTracker.cpp @@ -110,20 +110,14 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf void CombinationConditionTracker::isConditionMet( const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions, - const std::vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, const bool isPartialLink, - vector<ConditionState>& conditionCache, - std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const { + vector<ConditionState>& conditionCache) const { // So far, this is fine as there is at most one child having sliced output. for (const int childIndex : mChildren) { if (conditionCache[childIndex] == ConditionState::kNotEvaluated) { allConditions[childIndex]->isConditionMet(conditionParameters, allConditions, - dimensionFields, - isSubOutputDimensionFields, isPartialLink, - conditionCache, - dimensionsKeySet); + conditionCache); } } conditionCache[mIndex] = @@ -178,25 +172,6 @@ void CombinationConditionTracker::evaluateCondition( } } -ConditionState CombinationConditionTracker::getMetConditionDimension( - const std::vector<sp<ConditionTracker>>& allConditions, - const std::vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, - std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const { - vector<ConditionState> conditionCache(allConditions.size(), ConditionState::kNotEvaluated); - // So far, this is fine as there is at most one child having sliced output. - for (const int childIndex : mChildren) { - conditionCache[childIndex] = conditionCache[childIndex] | - allConditions[childIndex]->getMetConditionDimension( - allConditions, dimensionFields, isSubOutputDimensionFields, dimensionsKeySet); - } - evaluateCombinationCondition(mChildren, mLogicalOperation, conditionCache); - if (conditionCache[mIndex] == ConditionState::kTrue && dimensionsKeySet.empty()) { - dimensionsKeySet.insert(DEFAULT_DIMENSION_KEY); - } - return conditionCache[mIndex]; -} - bool CombinationConditionTracker::equalOutputDimensions( const std::vector<sp<ConditionTracker>>& allConditions, const vector<Matcher>& dimensions) const { diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.h b/cmds/statsd/src/condition/CombinationConditionTracker.h index 481cb200d8e6..e3d860127780 100644 --- a/cmds/statsd/src/condition/CombinationConditionTracker.h +++ b/cmds/statsd/src/condition/CombinationConditionTracker.h @@ -43,17 +43,8 @@ public: void isConditionMet(const ConditionKey& conditionParameters, const std::vector<sp<ConditionTracker>>& allConditions, - const vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, const bool isPartialLink, - std::vector<ConditionState>& conditionCache, - std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override; - - ConditionState getMetConditionDimension( - const std::vector<sp<ConditionTracker>>& allConditions, - const vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, - std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override; + std::vector<ConditionState>& conditionCache) const override; // Only one child predicate can have dimension. const std::set<HashableDimensionKey>* getChangedToTrueDimensions( diff --git a/cmds/statsd/src/condition/ConditionTracker.h b/cmds/statsd/src/condition/ConditionTracker.h index 1f4266b61cdf..e94ea6586f05 100644 --- a/cmds/statsd/src/condition/ConditionTracker.h +++ b/cmds/statsd/src/condition/ConditionTracker.h @@ -84,29 +84,14 @@ public: // condition. // [allConditions]: all condition trackers. This is needed because the condition evaluation is // done recursively - // [dimensionFields]: the needed dimension fields which should be all or subset of the condition - // tracker output dimension. - // [isSubOutputDimensionFields]: true if the needed dimension fields which is strictly subset of - // the condition tracker output dimension. // [isPartialLink]: true if the link specified by 'conditionParameters' contains all the fields // in the condition tracker output dimension. // [conditionCache]: the cache holding the condition evaluation values. - // [dimensionsKeySet]: the dimensions where the sliced condition is true. For combination - // condition, it assumes that only one child predicate is sliced. virtual void isConditionMet( const ConditionKey& conditionParameters, const std::vector<sp<ConditionTracker>>& allConditions, - const vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, const bool isPartialLink, - std::vector<ConditionState>& conditionCache, - std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const = 0; - - virtual ConditionState getMetConditionDimension( - const std::vector<sp<ConditionTracker>>& allConditions, - const vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, - std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const = 0; + std::vector<ConditionState>& conditionCache) const = 0; // return the list of LogMatchingTracker index that this ConditionTracker uses. virtual const std::set<int>& getLogTrackerIndex() const { diff --git a/cmds/statsd/src/condition/ConditionWizard.cpp b/cmds/statsd/src/condition/ConditionWizard.cpp index 23a9d371145e..4f44a69ba980 100644 --- a/cmds/statsd/src/condition/ConditionWizard.cpp +++ b/cmds/statsd/src/condition/ConditionWizard.cpp @@ -25,27 +25,15 @@ using std::string; using std::vector; ConditionState ConditionWizard::query(const int index, const ConditionKey& parameters, - const vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, - const bool isPartialLink, - std::unordered_set<HashableDimensionKey>* dimensionKeySet) { + const bool isPartialLink) { vector<ConditionState> cache(mAllConditions.size(), ConditionState::kNotEvaluated); mAllConditions[index]->isConditionMet( - parameters, mAllConditions, dimensionFields, isSubOutputDimensionFields, isPartialLink, - cache, *dimensionKeySet); + parameters, mAllConditions, isPartialLink, + cache); return cache[index]; } -ConditionState ConditionWizard::getMetConditionDimension( - const int index, const vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, - std::unordered_set<HashableDimensionKey>* dimensionsKeySet) const { - return mAllConditions[index]->getMetConditionDimension(mAllConditions, dimensionFields, - isSubOutputDimensionFields, - *dimensionsKeySet); -} - const set<HashableDimensionKey>* ConditionWizard::getChangedToTrueDimensions( const int index) const { return mAllConditions[index]->getChangedToTrueDimensions(mAllConditions); @@ -82,4 +70,4 @@ bool ConditionWizard::equalOutputDimensions(const int index, const vector<Matche } // namespace statsd } // namespace os -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/cmds/statsd/src/condition/ConditionWizard.h b/cmds/statsd/src/condition/ConditionWizard.h index 2c8814772839..892647910d9f 100644 --- a/cmds/statsd/src/condition/ConditionWizard.h +++ b/cmds/statsd/src/condition/ConditionWizard.h @@ -40,15 +40,7 @@ public: // The ConditionTracker at [conditionIndex] can be a CombinationConditionTracker. In this case, // the conditionParameters contains the parameters for it's children SimpleConditionTrackers. virtual ConditionState query(const int conditionIndex, const ConditionKey& conditionParameters, - const vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, - const bool isPartialLink, - std::unordered_set<HashableDimensionKey>* dimensionKeySet); - - virtual ConditionState getMetConditionDimension( - const int index, const vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, - std::unordered_set<HashableDimensionKey>* dimensionsKeySet) const; + const bool isPartialLink); virtual const std::set<HashableDimensionKey>* getChangedToTrueDimensions(const int index) const; virtual const std::set<HashableDimensionKey>* getChangedToFalseDimensions( diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp index 87104a34c009..0c92149f4c96 100644 --- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp +++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp @@ -344,11 +344,8 @@ void SimpleConditionTracker::evaluateCondition( void SimpleConditionTracker::isConditionMet( const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions, - const vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, const bool isPartialLink, - vector<ConditionState>& conditionCache, - std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const { + vector<ConditionState>& conditionCache) const { if (conditionCache[mIndex] != ConditionState::kNotEvaluated) { // it has been evaluated. @@ -360,18 +357,13 @@ void SimpleConditionTracker::isConditionMet( if (pair == conditionParameters.end()) { ConditionState conditionState = ConditionState::kNotEvaluated; - if (dimensionFields.size() > 0 && dimensionFields[0].mMatcher.getTag() == mDimensionTag) { - conditionState = conditionState | getMetConditionDimension( - allConditions, dimensionFields, isSubOutputDimensionFields, dimensionsKeySet); - } else { - conditionState = conditionState | mInitialValue; - if (!mSliced) { - const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY); - if (itr != mSlicedConditionState.end()) { - ConditionState sliceState = - itr->second > 0 ? ConditionState::kTrue : ConditionState::kFalse; - conditionState = conditionState | sliceState; - } + conditionState = conditionState | mInitialValue; + if (!mSliced) { + const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY); + if (itr != mSlicedConditionState.end()) { + ConditionState sliceState = + itr->second > 0 ? ConditionState::kTrue : ConditionState::kFalse; + conditionState = conditionState | sliceState; } } conditionCache[mIndex] = conditionState; @@ -389,15 +381,6 @@ void SimpleConditionTracker::isConditionMet( slice.second > 0 ? ConditionState::kTrue : ConditionState::kFalse; if (slice.first.contains(key)) { conditionState = conditionState | sliceState; - if (sliceState == ConditionState::kTrue && dimensionFields.size() > 0) { - if (isSubOutputDimensionFields) { - HashableDimensionKey dimensionKey; - filterValues(dimensionFields, slice.first.getValues(), &dimensionKey); - dimensionsKeySet.insert(dimensionKey); - } else { - dimensionsKeySet.insert(slice.first); - } - } } } } else { @@ -407,15 +390,6 @@ void SimpleConditionTracker::isConditionMet( ConditionState sliceState = startedCountIt->second > 0 ? ConditionState::kTrue : ConditionState::kFalse; conditionState = conditionState | sliceState; - if (sliceState == ConditionState::kTrue && dimensionFields.size() > 0) { - if (isSubOutputDimensionFields) { - HashableDimensionKey dimensionKey; - filterValues(dimensionFields, startedCountIt->first.getValues(), &dimensionKey); - dimensionsKeySet.insert(dimensionKey); - } else { - dimensionsKeySet.insert(startedCountIt->first); - } - } } } @@ -423,41 +397,6 @@ void SimpleConditionTracker::isConditionMet( VLOG("Predicate %lld return %d", (long long)mConditionId, conditionCache[mIndex]); } -ConditionState SimpleConditionTracker::getMetConditionDimension( - const std::vector<sp<ConditionTracker>>& allConditions, - const vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, - std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const { - ConditionState conditionState = mInitialValue; - if (dimensionFields.size() == 0 || mOutputDimensions.size() == 0 || - dimensionFields[0].mMatcher.getTag() != mOutputDimensions[0].mMatcher.getTag()) { - const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY); - if (itr != mSlicedConditionState.end()) { - ConditionState sliceState = - itr->second > 0 ? ConditionState::kTrue : ConditionState::kFalse; - conditionState = conditionState | sliceState; - } - return conditionState; - } - - for (const auto& slice : mSlicedConditionState) { - ConditionState sliceState = - slice.second > 0 ? ConditionState::kTrue : ConditionState::kFalse; - conditionState = conditionState | sliceState; - - if (sliceState == ConditionState::kTrue && dimensionFields.size() > 0) { - if (isSubOutputDimensionFields) { - HashableDimensionKey dimensionKey; - filterValues(dimensionFields, slice.first.getValues(), &dimensionKey); - dimensionsKeySet.insert(dimensionKey); - } else { - dimensionsKeySet.insert(slice.first); - } - } - } - return conditionState; -} - } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.h b/cmds/statsd/src/condition/SimpleConditionTracker.h index 47d1eceb9022..5c5cc565f783 100644 --- a/cmds/statsd/src/condition/SimpleConditionTracker.h +++ b/cmds/statsd/src/condition/SimpleConditionTracker.h @@ -48,17 +48,8 @@ public: void isConditionMet(const ConditionKey& conditionParameters, const std::vector<sp<ConditionTracker>>& allConditions, - const vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, const bool isPartialLink, - std::vector<ConditionState>& conditionCache, - std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override; - - ConditionState getMetConditionDimension( - const std::vector<sp<ConditionTracker>>& allConditions, - const vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, - std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override; + std::vector<ConditionState>& conditionCache) const override; virtual const std::set<HashableDimensionKey>* getChangedToTrueDimensions( const std::vector<sp<ConditionTracker>>& allConditions) const { diff --git a/cmds/statsd/src/condition/StateTracker.cpp b/cmds/statsd/src/condition/StateTracker.cpp index 1965ce6015ff..18c7178dd7d7 100644 --- a/cmds/statsd/src/condition/StateTracker.cpp +++ b/cmds/statsd/src/condition/StateTracker.cpp @@ -178,11 +178,8 @@ void StateTracker::evaluateCondition(const LogEvent& event, void StateTracker::isConditionMet( const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions, - const vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, const bool isPartialLink, - vector<ConditionState>& conditionCache, - std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const { + vector<ConditionState>& conditionCache) const { if (conditionCache[mIndex] != ConditionState::kNotEvaluated) { // it has been evaluated. VLOG("Yes, already evaluated, %lld %d", (long long)mConditionId, conditionCache[mIndex]); @@ -193,10 +190,6 @@ void StateTracker::isConditionMet( if (pair == conditionParameters.end()) { if (mSlicedState.size() > 0) { conditionCache[mIndex] = ConditionState::kTrue; - - for (const auto& state : mSlicedState) { - dimensionsKeySet.insert(state.second); - } } else { conditionCache[mIndex] = ConditionState::kUnknown; } @@ -208,25 +201,9 @@ void StateTracker::isConditionMet( auto it = mSlicedState.find(primaryKey); if (it != mSlicedState.end()) { conditionCache[mIndex] = ConditionState::kTrue; - dimensionsKeySet.insert(it->second); - } -} - -ConditionState StateTracker::getMetConditionDimension( - const std::vector<sp<ConditionTracker>>& allConditions, - const vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, - std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const { - if (mSlicedState.size() > 0) { - for (const auto& state : mSlicedState) { - dimensionsKeySet.insert(state.second); - } - return ConditionState::kTrue; } - - return mInitialValue; } } // namespace statsd } // namespace os -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/cmds/statsd/src/condition/StateTracker.h b/cmds/statsd/src/condition/StateTracker.h index 2bdf98c34c32..5ae4441713cd 100644 --- a/cmds/statsd/src/condition/StateTracker.h +++ b/cmds/statsd/src/condition/StateTracker.h @@ -55,22 +55,8 @@ public: */ void isConditionMet(const ConditionKey& conditionParameters, const std::vector<sp<ConditionTracker>>& allConditions, - const vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, const bool isPartialLink, - std::vector<ConditionState>& conditionCache, - std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override; - - /** - * Note: dimensionFields will be ignored in StateTracker, because we demand metrics - * must take the entire dimension fields from StateTracker. This is to make implementation - * simple and efficient. - */ - ConditionState getMetConditionDimension( - const std::vector<sp<ConditionTracker>>& allConditions, - const vector<Matcher>& dimensionFields, - const bool isSubOutputDimensionFields, - std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override; + std::vector<ConditionState>& conditionCache) const override; virtual const std::set<HashableDimensionKey>* getChangedToTrueDimensions( const std::vector<sp<ConditionTracker>>& allConditions) const { @@ -128,4 +114,4 @@ private: } // namespace statsd } // namespace os -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp index c023e6f77e7c..23d025f82c26 100644 --- a/cmds/statsd/src/metrics/CountMetricProducer.cpp +++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp @@ -48,7 +48,6 @@ const int FIELD_ID_COUNT_METRICS = 5; const int FIELD_ID_TIME_BASE = 9; const int FIELD_ID_BUCKET_SIZE = 10; const int FIELD_ID_DIMENSION_PATH_IN_WHAT = 11; -const int FIELD_ID_DIMENSION_PATH_IN_CONDITION = 12; const int FIELD_ID_IS_ACTIVE = 14; // for CountMetricDataWrapper @@ -82,12 +81,7 @@ CountMetricProducer::CountMetricProducer(const ConfigKey& key, const CountMetric mContainANYPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what()); } - mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what()) || - HasPositionALL(metric.dimensions_in_condition()); - - if (metric.has_dimensions_in_condition()) { - translateFieldMatcher(metric.dimensions_in_condition(), &mDimensionsInCondition); - } + mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what()); if (metric.links().size() > 0) { for (const auto& link : metric.links()) { @@ -100,8 +94,6 @@ CountMetricProducer::CountMetricProducer(const ConfigKey& key, const CountMetric mConditionSliced = true; } - mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0); - flushIfNeededLocked(startTimeNs); // Adjust start for partial bucket mCurrentBucketStartTimeNs = startTimeNs; @@ -171,13 +163,6 @@ void CountMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs, writeDimensionPathToProto(mDimensionsInWhat, protoOutput); protoOutput->end(dimenPathToken); } - if (!mDimensionsInCondition.empty()) { - uint64_t dimenPathToken = protoOutput->start( - FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_PATH_IN_CONDITION); - writeDimensionPathToProto(mDimensionsInCondition, protoOutput); - protoOutput->end(dimenPathToken); - } - } uint64_t protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_COUNT_METRICS); diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp index 96fbf7fb5ebe..cca793b2146a 100644 --- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp +++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp @@ -47,7 +47,6 @@ const int FIELD_ID_DURATION_METRICS = 6; const int FIELD_ID_TIME_BASE = 9; const int FIELD_ID_BUCKET_SIZE = 10; const int FIELD_ID_DIMENSION_PATH_IN_WHAT = 11; -const int FIELD_ID_DIMENSION_PATH_IN_CONDITION = 12; const int FIELD_ID_IS_ACTIVE = 14; // for DurationMetricDataWrapper const int FIELD_ID_DATA = 1; @@ -100,12 +99,7 @@ DurationMetricProducer::DurationMetricProducer(const ConfigKey& key, const Durat ALOGE("Position ANY in dimension_in_what not supported."); } - if (metric.has_dimensions_in_condition()) { - translateFieldMatcher(metric.dimensions_in_condition(), &mDimensionsInCondition); - } - - mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what()) || - HasPositionALL(metric.dimensions_in_condition()); + mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what()); if (metric.links().size() > 0) { for (const auto& link : metric.links()) { @@ -115,19 +109,16 @@ DurationMetricProducer::DurationMetricProducer(const ConfigKey& key, const Durat translateFieldMatcher(link.fields_in_condition(), &mc.conditionFields); mMetric2ConditionLinks.push_back(mc); } + mConditionSliced = true; } - mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0); mUnSlicedPartCondition = ConditionState::kUnknown; mUseWhatDimensionAsInternalDimension = equalDimensions(mDimensionsInWhat, mInternalDimensions); - if (mWizard != nullptr && mConditionTrackerIndex >= 0) { - mSameConditionDimensionsInTracker = - mWizard->equalOutputDimensions(mConditionTrackerIndex, mDimensionsInCondition); - if (mMetric2ConditionLinks.size() == 1) { - mHasLinksToAllConditionDimensionsInTracker = - mWizard->equalOutputDimensions(mConditionTrackerIndex, - mMetric2ConditionLinks.begin()->conditionFields); - } + if (mWizard != nullptr && mConditionTrackerIndex >= 0 && + mMetric2ConditionLinks.size() == 1) { + mHasLinksToAllConditionDimensionsInTracker = + mWizard->equalOutputDimensions(mConditionTrackerIndex, + mMetric2ConditionLinks.begin()->conditionFields); } flushIfNeededLocked(startTimeNs); // Adjust start for partial bucket @@ -164,13 +155,13 @@ unique_ptr<DurationTracker> DurationMetricProducer::createDurationTracker( case DurationMetric_AggregationType_SUM: return make_unique<OringDurationTracker>( mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex, - mDimensionsInCondition, mNested, mCurrentBucketStartTimeNs, mCurrentBucketNum, + mNested, mCurrentBucketStartTimeNs, mCurrentBucketNum, mTimeBaseNs, mBucketSizeNs, mConditionSliced, mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers); case DurationMetric_AggregationType_MAX_SPARSE: return make_unique<MaxDurationTracker>( mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex, - mDimensionsInCondition, mNested, mCurrentBucketStartTimeNs, mCurrentBucketNum, + mNested, mCurrentBucketStartTimeNs, mCurrentBucketNum, mTimeBaseNs, mBucketSizeNs, mConditionSliced, mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers); } @@ -178,13 +169,11 @@ unique_ptr<DurationTracker> DurationMetricProducer::createDurationTracker( // SlicedConditionChange optimization case 1: // 1. If combination condition, logical operation is AND, only one sliced child predicate. -// 2. No condition in dimension -// 3. The links covers all dimension fields in the sliced child condition predicate. +// 2. The links covers all dimension fields in the sliced child condition predicate. void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt1(bool condition, const int64_t eventTime) { if (mMetric2ConditionLinks.size() != 1 || - !mHasLinksToAllConditionDimensionsInTracker || - !mDimensionsInCondition.empty()) { + !mHasLinksToAllConditionDimensionsInTracker) { return; } @@ -249,178 +238,20 @@ void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt1(bool conditio } } - -// SlicedConditionChange optimization case 2: -// 1. If combination condition, logical operation is AND, only one sliced child predicate. -// 2. Has dimensions_in_condition and it equals to the output dimensions of the sliced predicate. -void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt2(bool condition, - const int64_t eventTime) { - if (mMetric2ConditionLinks.size() > 1 || !mSameConditionDimensionsInTracker) { - return; - } - - auto dimensionsChangedToTrue = mWizard->getChangedToTrueDimensions(mConditionTrackerIndex); - auto dimensionsChangedToFalse = mWizard->getChangedToFalseDimensions(mConditionTrackerIndex); - - bool currentUnSlicedPartCondition = true; - if (!mWizard->IsSimpleCondition(mConditionTrackerIndex)) { - ConditionState unslicedPartState = - mWizard->getUnSlicedPartConditionState(mConditionTrackerIndex); - // When the unsliced part is still false, return directly. - if (mUnSlicedPartCondition == ConditionState::kFalse && - unslicedPartState == ConditionState::kFalse) { - return; - } - mUnSlicedPartCondition = unslicedPartState; - currentUnSlicedPartCondition = mUnSlicedPartCondition > 0; - } - - const std::set<HashableDimensionKey>* trueDimensionsToProcess = nullptr; - const std::set<HashableDimensionKey>* falseDimensionsToProcess = nullptr; - - std::set<HashableDimensionKey> currentTrueConditionDimensions; - if (dimensionsChangedToTrue == nullptr || dimensionsChangedToFalse == nullptr || - (dimensionsChangedToTrue->empty() && dimensionsChangedToFalse->empty())) { - mWizard->getTrueSlicedDimensions(mConditionTrackerIndex, ¤tTrueConditionDimensions); - trueDimensionsToProcess = ¤tTrueConditionDimensions; - } else if (currentUnSlicedPartCondition) { - // Handles the condition change from the sliced predicate. If the unsliced condition state - // is not true, not need to do anything. - trueDimensionsToProcess = dimensionsChangedToTrue; - falseDimensionsToProcess = dimensionsChangedToFalse; - } - - if (trueDimensionsToProcess == nullptr && falseDimensionsToProcess == nullptr) { - return; - } - - for (auto& whatIt : mCurrentSlicedDurationTrackerMap) { - if (falseDimensionsToProcess != nullptr) { - for (const auto& changedDim : *falseDimensionsToProcess) { - auto condIt = whatIt.second.find(changedDim); - if (condIt != whatIt.second.end()) { - condIt->second->onConditionChanged(false, eventTime); - } - } - } - if (trueDimensionsToProcess != nullptr) { - HashableDimensionKey linkedConditionDimensionKey; - if (!trueDimensionsToProcess->empty() && mMetric2ConditionLinks.size() == 1) { - getDimensionForCondition(whatIt.first.getValues(), - mMetric2ConditionLinks[0], - &linkedConditionDimensionKey); - } - for (auto& trueDim : *trueDimensionsToProcess) { - auto condIt = whatIt.second.find(trueDim); - if (condIt != whatIt.second.end()) { - condIt->second->onConditionChanged( - currentUnSlicedPartCondition, eventTime); - } else { - if (mMetric2ConditionLinks.size() == 0 || - trueDim.contains(linkedConditionDimensionKey)) { - if (!whatIt.second.empty()) { - auto newEventKey = MetricDimensionKey(whatIt.first, trueDim); - if (hitGuardRailLocked(newEventKey)) { - continue; - } - unique_ptr<DurationTracker> newTracker = - whatIt.second.begin()->second->clone(eventTime); - if (newTracker != nullptr) { - newTracker->setEventKey(newEventKey); - newTracker->onConditionChanged(true, eventTime); - whatIt.second[trueDim] = std::move(newTracker); - } - } - } - } - } - } - } -} - void DurationMetricProducer::onSlicedConditionMayChangeInternalLocked(bool overallCondition, const int64_t eventTimeNs) { bool changeDimTrackable = mWizard->IsChangedDimensionTrackable(mConditionTrackerIndex); - if (changeDimTrackable && mHasLinksToAllConditionDimensionsInTracker && - mDimensionsInCondition.empty()) { + if (changeDimTrackable && mHasLinksToAllConditionDimensionsInTracker) { onSlicedConditionMayChangeLocked_opt1(overallCondition, eventTimeNs); return; } - if (changeDimTrackable && mSameConditionDimensionsInTracker && - mMetric2ConditionLinks.size() <= 1) { - onSlicedConditionMayChangeLocked_opt2(overallCondition, eventTimeNs); - return; - } - // Now for each of the on-going event, check if the condition has changed for them. for (auto& whatIt : mCurrentSlicedDurationTrackerMap) { for (auto& pair : whatIt.second) { pair.second->onSlicedConditionMayChange(overallCondition, eventTimeNs); } } - - if (mDimensionsInCondition.empty()) { - return; - } - - if (mMetric2ConditionLinks.empty()) { - std::unordered_set<HashableDimensionKey> conditionDimensionsKeySet; - mWizard->getMetConditionDimension(mConditionTrackerIndex, mDimensionsInCondition, - !mSameConditionDimensionsInTracker, - &conditionDimensionsKeySet); - for (const auto& whatIt : mCurrentSlicedDurationTrackerMap) { - for (const auto& pair : whatIt.second) { - conditionDimensionsKeySet.erase(pair.first); - } - } - for (const auto& conditionDimension : conditionDimensionsKeySet) { - for (auto& whatIt : mCurrentSlicedDurationTrackerMap) { - if (!whatIt.second.empty()) { - auto newEventKey = MetricDimensionKey(whatIt.first, conditionDimension); - if (hitGuardRailLocked(newEventKey)) { - continue; - } - unique_ptr<DurationTracker> newTracker = - whatIt.second.begin()->second->clone(eventTimeNs); - if (newTracker != nullptr) { - newTracker->setEventKey(MetricDimensionKey(newEventKey)); - newTracker->onSlicedConditionMayChange(overallCondition, eventTimeNs); - whatIt.second[conditionDimension] = std::move(newTracker); - } - } - } - } - } else { - for (auto& whatIt : mCurrentSlicedDurationTrackerMap) { - ConditionKey conditionKey; - for (const auto& link : mMetric2ConditionLinks) { - getDimensionForCondition(whatIt.first.getValues(), link, - &conditionKey[link.conditionId]); - } - std::unordered_set<HashableDimensionKey> conditionDimensionsKeys; - mWizard->query(mConditionTrackerIndex, conditionKey, mDimensionsInCondition, - !mSameConditionDimensionsInTracker, - !mHasLinksToAllConditionDimensionsInTracker, - &conditionDimensionsKeys); - - for (const auto& conditionDimension : conditionDimensionsKeys) { - if (!whatIt.second.empty() && - whatIt.second.find(conditionDimension) == whatIt.second.end()) { - auto newEventKey = MetricDimensionKey(whatIt.first, conditionDimension); - if (hitGuardRailLocked(newEventKey)) { - continue; - } - auto newTracker = whatIt.second.begin()->second->clone(eventTimeNs); - if (newTracker != nullptr) { - newTracker->setEventKey(newEventKey); - newTracker->onSlicedConditionMayChange(overallCondition, eventTimeNs); - whatIt.second[conditionDimension] = std::move(newTracker); - } - } - } - } - } } void DurationMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition, @@ -526,12 +357,6 @@ void DurationMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs, writeDimensionPathToProto(mDimensionsInWhat, protoOutput); protoOutput->end(dimenPathToken); } - if (!mDimensionsInCondition.empty()) { - uint64_t dimenPathToken = protoOutput->start( - FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_PATH_IN_CONDITION); - writeDimensionPathToProto(mDimensionsInCondition, protoOutput); - protoOutput->end(dimenPathToken); - } } uint64_t protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DURATION_METRICS); @@ -790,52 +615,24 @@ void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, bool condition; ConditionKey conditionKey; - std::unordered_set<HashableDimensionKey> dimensionKeysInCondition; if (mConditionSliced) { for (const auto& link : mMetric2ConditionLinks) { getDimensionForCondition(event.getValues(), link, &conditionKey[link.conditionId]); } auto conditionState = - mWizard->query(mConditionTrackerIndex, conditionKey, mDimensionsInCondition, - !mSameConditionDimensionsInTracker, - !mHasLinksToAllConditionDimensionsInTracker, - &dimensionKeysInCondition); + mWizard->query(mConditionTrackerIndex, conditionKey, + !mHasLinksToAllConditionDimensionsInTracker); condition = conditionState == ConditionState::kTrue; - if (mDimensionsInCondition.empty() && condition) { - dimensionKeysInCondition.insert(DEFAULT_DIMENSION_KEY); - } } else { // TODO: The unknown condition state is not handled here, we should fix it. condition = mCondition == ConditionState::kTrue; - if (condition) { - dimensionKeysInCondition.insert(DEFAULT_DIMENSION_KEY); - } } condition = condition && mIsActive; - if (dimensionKeysInCondition.empty()) { - handleStartEvent(MetricDimensionKey(dimensionInWhat, DEFAULT_DIMENSION_KEY), - conditionKey, condition, event); - } else { - auto whatIt = mCurrentSlicedDurationTrackerMap.find(dimensionInWhat); - // If the what dimension is already there, we should update all the trackers even - // the condition is false. - if (whatIt != mCurrentSlicedDurationTrackerMap.end()) { - for (const auto& condIt : whatIt->second) { - const bool cond = dimensionKeysInCondition.find(condIt.first) != - dimensionKeysInCondition.end() && condition; - handleStartEvent(MetricDimensionKey(dimensionInWhat, condIt.first), - conditionKey, cond, event); - dimensionKeysInCondition.erase(condIt.first); - } - } - for (const auto& conditionDimension : dimensionKeysInCondition) { - handleStartEvent(MetricDimensionKey(dimensionInWhat, conditionDimension), conditionKey, - condition, event); - } - } + handleStartEvent(MetricDimensionKey(dimensionInWhat, DEFAULT_DIMENSION_KEY), + conditionKey, condition, event); } size_t DurationMetricProducer::byteSizeLocked() const { diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp index a64bbc1056e0..1f423cd384ef 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp @@ -48,7 +48,6 @@ const int FIELD_ID_GAUGE_METRICS = 8; const int FIELD_ID_TIME_BASE = 9; const int FIELD_ID_BUCKET_SIZE = 10; const int FIELD_ID_DIMENSION_PATH_IN_WHAT = 11; -const int FIELD_ID_DIMENSION_PATH_IN_CONDITION = 12; const int FIELD_ID_IS_ACTIVE = 14; // for GaugeMetricDataWrapper const int FIELD_ID_DATA = 1; @@ -115,10 +114,6 @@ GaugeMetricProducer::GaugeMetricProducer( mContainANYPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what()); } - if (metric.has_dimensions_in_condition()) { - translateFieldMatcher(metric.dimensions_in_condition(), &mDimensionsInCondition); - } - if (metric.links().size() > 0) { for (const auto& link : metric.links()) { Metric2Condition mc; @@ -127,10 +122,9 @@ GaugeMetricProducer::GaugeMetricProducer( translateFieldMatcher(link.fields_in_condition(), &mc.conditionFields); mMetric2ConditionLinks.push_back(mc); } + mConditionSliced = true; } - mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0); - mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what()) || - HasPositionALL(metric.dimensions_in_condition()); + mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what()); flushIfNeededLocked(startTimeNs); // Kicks off the puller immediately. @@ -209,12 +203,6 @@ void GaugeMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs, writeDimensionPathToProto(mDimensionsInWhat, protoOutput); protoOutput->end(dimenPathToken); } - if (!mDimensionsInCondition.empty()) { - uint64_t dimenPathToken = protoOutput->start( - FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_PATH_IN_CONDITION); - writeDimensionPathToProto(mDimensionsInCondition, protoOutput); - protoOutput->end(dimenPathToken); - } } uint64_t protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_GAUGE_METRICS); diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp index 92752b29ecda..1ab4fdf6e90c 100644 --- a/cmds/statsd/src/metrics/MetricProducer.cpp +++ b/cmds/statsd/src/metrics/MetricProducer.cpp @@ -52,38 +52,24 @@ void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const Lo bool condition; ConditionKey conditionKey; - std::unordered_set<HashableDimensionKey> dimensionKeysInCondition; if (mConditionSliced) { for (const auto& link : mMetric2ConditionLinks) { getDimensionForCondition(event.getValues(), link, &conditionKey[link.conditionId]); } auto conditionState = - mWizard->query(mConditionTrackerIndex, conditionKey, mDimensionsInCondition, - !mSameConditionDimensionsInTracker, - !mHasLinksToAllConditionDimensionsInTracker, - &dimensionKeysInCondition); + mWizard->query(mConditionTrackerIndex, conditionKey, + !mHasLinksToAllConditionDimensionsInTracker); condition = (conditionState == ConditionState::kTrue); } else { // TODO: The unknown condition state is not handled here, we should fix it. condition = mCondition == ConditionState::kTrue; } - if (mDimensionsInCondition.empty() && condition) { - dimensionKeysInCondition.insert(DEFAULT_DIMENSION_KEY); - } - HashableDimensionKey dimensionInWhat; filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhat); MetricDimensionKey metricKey(dimensionInWhat, DEFAULT_DIMENSION_KEY); - for (const auto& conditionDimensionKey : dimensionKeysInCondition) { - metricKey.setDimensionKeyInCondition(conditionDimensionKey); - onMatchedLogEventInternalLocked( - matcherIndex, metricKey, conditionKey, condition, event); - } - if (dimensionKeysInCondition.empty()) { - onMatchedLogEventInternalLocked( - matcherIndex, metricKey, conditionKey, condition, event); - } + onMatchedLogEventInternalLocked( + matcherIndex, metricKey, conditionKey, condition, event); } bool MetricProducer::evaluateActiveStateLocked(int64_t elapsedTimestampNs) { diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h index 09ad2903fa4c..94f833b20814 100644 --- a/cmds/statsd/src/metrics/MetricProducer.h +++ b/cmds/statsd/src/metrics/MetricProducer.h @@ -88,7 +88,6 @@ public: mConditionTrackerIndex(conditionIndex), mContainANYPositionInDimensionsInWhat(false), mSliceByPositionALL(false), - mSameConditionDimensionsInTracker(false), mHasLinksToAllConditionDimensionsInTracker(false), mIsActive(true) { } @@ -349,15 +348,10 @@ protected: int mConditionTrackerIndex; vector<Matcher> mDimensionsInWhat; // The dimensions_in_what defined in statsd_config - vector<Matcher> mDimensionsInCondition; // The dimensions_in_condition defined in statsd_config bool mContainANYPositionInDimensionsInWhat; bool mSliceByPositionALL; - // True iff the condition dimensions equal to the sliced dimensions in the simple condition - // tracker. This field is always false for combinational condition trackers. - bool mSameConditionDimensionsInTracker; - // True iff the metric to condition links cover all dimension fields in the condition tracker. // This field is always false for combinational condition trackers. bool mHasLinksToAllConditionDimensionsInTracker; diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h index 8efca1e10de5..3dad61465416 100644 --- a/cmds/statsd/src/metrics/MetricsManager.h +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -260,17 +260,6 @@ private: FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents); FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm); FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation); - FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition); - FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition); - FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_OR_CombinationCondition); - FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_OR_CombinationCondition); - - FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_SimpleCondition); - FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_SimpleCondition); - FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_SimpleCondition); - FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_AND_CombinationCondition); - FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_AND_CombinationCondition); - FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_AND_CombinationCondition); FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket); FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets); diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp index 0e33a0f9f29b..bc1602497c39 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -51,7 +51,6 @@ const int FIELD_ID_VALUE_METRICS = 7; const int FIELD_ID_TIME_BASE = 9; const int FIELD_ID_BUCKET_SIZE = 10; const int FIELD_ID_DIMENSION_PATH_IN_WHAT = 11; -const int FIELD_ID_DIMENSION_PATH_IN_CONDITION = 12; const int FIELD_ID_IS_ACTIVE = 14; // for ValueMetricDataWrapper const int FIELD_ID_DATA = 1; @@ -127,10 +126,6 @@ ValueMetricProducer::ValueMetricProducer( mContainANYPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what()); } - if (metric.has_dimensions_in_condition()) { - translateFieldMatcher(metric.dimensions_in_condition(), &mDimensionsInCondition); - } - if (metric.links().size() > 0) { for (const auto& link : metric.links()) { Metric2Condition mc; @@ -139,11 +134,10 @@ ValueMetricProducer::ValueMetricProducer( translateFieldMatcher(link.fields_in_condition(), &mc.conditionFields); mMetric2ConditionLinks.push_back(mc); } + mConditionSliced = true; } - mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0); - mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what()) || - HasPositionALL(metric.dimensions_in_condition()); + mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what()); int64_t numBucketsForward = calcBucketsForwardCount(startTimeNs); mCurrentBucketNum += numBucketsForward; @@ -243,12 +237,6 @@ void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs, writeDimensionPathToProto(mDimensionsInWhat, protoOutput); protoOutput->end(dimenPathToken); } - if (!mDimensionsInCondition.empty()) { - uint64_t dimenPathToken = - protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_PATH_IN_CONDITION); - writeDimensionPathToProto(mDimensionsInCondition, protoOutput); - protoOutput->end(dimenPathToken); - } } uint64_t protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_VALUE_METRICS); diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h index 081e61ed21fa..6b5c2994a0c8 100644 --- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h +++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h @@ -60,7 +60,7 @@ class DurationTracker { public: DurationTracker(const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey, sp<ConditionWizard> wizard, int conditionIndex, - const std::vector<Matcher>& dimensionInCondition, bool nesting, + bool nesting, int64_t currentBucketStartNs, int64_t currentBucketNum, int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced, bool fullLink, const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers) @@ -70,7 +70,6 @@ public: mWizard(wizard), mConditionTrackerIndex(conditionIndex), mBucketSizeNs(bucketSizeNs), - mDimensionInCondition(dimensionInCondition), mNested(nesting), mCurrentBucketStartTimeNs(currentBucketStartNs), mDuration(0), @@ -180,8 +179,6 @@ protected: const int64_t mBucketSizeNs; - const std::vector<Matcher>& mDimensionInCondition; - const bool mNested; int64_t mCurrentBucketStartTimeNs; @@ -196,7 +193,6 @@ protected: const bool mConditionSliced; - bool mSameConditionDimensionsInTracker; bool mHasLinksToAllConditionDimensionsInTracker; std::vector<sp<DurationAnomalyTracker>> mAnomalyTrackers; diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp index 6868b8c24c71..df66cb0c53e5 100644 --- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp +++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp @@ -27,18 +27,14 @@ namespace statsd { MaxDurationTracker::MaxDurationTracker(const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey, sp<ConditionWizard> wizard, int conditionIndex, - const vector<Matcher>& dimensionInCondition, bool nesting, + bool nesting, int64_t currentBucketStartNs, int64_t currentBucketNum, int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced, bool fullLink, const vector<sp<DurationAnomalyTracker>>& anomalyTrackers) - : DurationTracker(key, id, eventKey, wizard, conditionIndex, dimensionInCondition, nesting, + : DurationTracker(key, id, eventKey, wizard, conditionIndex, nesting, currentBucketStartNs, currentBucketNum, startTimeNs, bucketSizeNs, conditionSliced, fullLink, anomalyTrackers) { - if (mWizard != nullptr) { - mSameConditionDimensionsInTracker = - mWizard->equalOutputDimensions(conditionIndex, mDimensionInCondition); - } } unique_ptr<DurationTracker> MaxDurationTracker::clone(const int64_t eventTime) { @@ -252,17 +248,11 @@ void MaxDurationTracker::onSlicedConditionMayChange(bool overallCondition, if (pair.second.state == kStopped) { continue; } - std::unordered_set<HashableDimensionKey> conditionDimensionKeySet; ConditionState conditionState = mWizard->query( - mConditionTrackerIndex, pair.second.conditionKeys, mDimensionInCondition, - !mSameConditionDimensionsInTracker, - !mHasLinksToAllConditionDimensionsInTracker, - &conditionDimensionKeySet); - bool conditionMet = - (conditionState == ConditionState::kTrue) && - (mDimensionInCondition.size() == 0 || - conditionDimensionKeySet.find(mEventKey.getDimensionKeyInCondition()) != - conditionDimensionKeySet.end()); + mConditionTrackerIndex, pair.second.conditionKeys, + !mHasLinksToAllConditionDimensionsInTracker); + bool conditionMet = (conditionState == ConditionState::kTrue); + VLOG("key: %s, condition: %d", pair.first.toString().c_str(), conditionMet); noteConditionChanged(pair.first, conditionMet, timestamp); } diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h index 8e8f2cd6c582..d0371da096ea 100644 --- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h +++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h @@ -30,7 +30,7 @@ class MaxDurationTracker : public DurationTracker { public: MaxDurationTracker(const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey, sp<ConditionWizard> wizard, int conditionIndex, - const std::vector<Matcher>& dimensionInCondition, bool nesting, + bool nesting, int64_t currentBucketStartNs, int64_t currentBucketNum, int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced, bool fullLink, diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp index 956383a99eea..b0fd975b2328 100644 --- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp +++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp @@ -26,20 +26,16 @@ using std::pair; OringDurationTracker::OringDurationTracker( const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey, - sp<ConditionWizard> wizard, int conditionIndex, const vector<Matcher>& dimensionInCondition, + sp<ConditionWizard> wizard, int conditionIndex, bool nesting, int64_t currentBucketStartNs, int64_t currentBucketNum, int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced, bool fullLink, const vector<sp<DurationAnomalyTracker>>& anomalyTrackers) - : DurationTracker(key, id, eventKey, wizard, conditionIndex, dimensionInCondition, nesting, + : DurationTracker(key, id, eventKey, wizard, conditionIndex, nesting, currentBucketStartNs, currentBucketNum, startTimeNs, bucketSizeNs, conditionSliced, fullLink, anomalyTrackers), mStarted(), mPaused() { mLastStartTime = 0; - if (mWizard != nullptr) { - mSameConditionDimensionsInTracker = - mWizard->equalOutputDimensions(conditionIndex, mDimensionInCondition); - } } unique_ptr<DurationTracker> OringDurationTracker::clone(const int64_t eventTime) { @@ -227,17 +223,10 @@ void OringDurationTracker::onSlicedConditionMayChange(bool overallCondition, ++it; continue; } - std::unordered_set<HashableDimensionKey> conditionDimensionKeySet; ConditionState conditionState = mWizard->query(mConditionTrackerIndex, condIt->second, - mDimensionInCondition, - !mSameConditionDimensionsInTracker, - !mHasLinksToAllConditionDimensionsInTracker, - &conditionDimensionKeySet); - if (conditionState != ConditionState::kTrue || - (mDimensionInCondition.size() != 0 && - conditionDimensionKeySet.find(mEventKey.getDimensionKeyInCondition()) == - conditionDimensionKeySet.end())) { + !mHasLinksToAllConditionDimensionsInTracker); + if (conditionState != ConditionState::kTrue) { startedToPaused.push_back(*it); it = mStarted.erase(it); VLOG("Key %s started -> paused", key.toString().c_str()); @@ -262,17 +251,10 @@ void OringDurationTracker::onSlicedConditionMayChange(bool overallCondition, ++it; continue; } - std::unordered_set<HashableDimensionKey> conditionDimensionKeySet; ConditionState conditionState = mWizard->query(mConditionTrackerIndex, mConditionKeyMap[key], - mDimensionInCondition, - !mSameConditionDimensionsInTracker, - !mHasLinksToAllConditionDimensionsInTracker, - &conditionDimensionKeySet); - if (conditionState == ConditionState::kTrue && - (mDimensionInCondition.size() == 0 || - conditionDimensionKeySet.find(mEventKey.getDimensionKeyInCondition()) != - conditionDimensionKeySet.end())) { + !mHasLinksToAllConditionDimensionsInTracker); + if (conditionState == ConditionState::kTrue) { pausedToStarted.push_back(*it); it = mPaused.erase(it); VLOG("Key %s paused -> started", key.toString().c_str()); diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h index 8e73256d4a01..43c48d5f536b 100644 --- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h +++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h @@ -29,7 +29,7 @@ class OringDurationTracker : public DurationTracker { public: OringDurationTracker(const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey, sp<ConditionWizard> wizard, - int conditionIndex, const std::vector<Matcher>& dimensionInCondition, + int conditionIndex, bool nesting, int64_t currentBucketStartNs, int64_t currentBucketNum, int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced, bool fullLink, diff --git a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp index e826a52c2f33..6eaa2311e5ed 100644 --- a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp +++ b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp @@ -268,8 +268,6 @@ TEST(SimpleConditionTrackerTest, TestSlicedCondition) { std::vector<sp<ConditionTracker>> allConditions; for (Position position : { Position::FIRST, Position::LAST}) { - vector<Matcher> dimensionInCondition; - std::unordered_set<HashableDimensionKey> dimensionKeys; SimplePredicate simplePredicate = getWakeLockHeldCondition( true /*nesting*/, true /*default to false*/, true /*output slice by uid*/, @@ -321,9 +319,9 @@ TEST(SimpleConditionTrackerTest, TestSlicedCondition) { const auto queryKey = getWakeLockQueryKey(position, uids, conditionName); conditionCache[0] = ConditionState::kNotEvaluated; - conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition, - false, false, - conditionCache, dimensionKeys); + conditionTracker.isConditionMet(queryKey, allPredicates, + false, + conditionCache); EXPECT_EQ(ConditionState::kTrue, conditionCache[0]); // another wake lock acquired by this uid @@ -389,9 +387,9 @@ TEST(SimpleConditionTrackerTest, TestSlicedCondition) { // query again conditionCache[0] = ConditionState::kNotEvaluated; - conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition, - false, false, - conditionCache, dimensionKeys); + conditionTracker.isConditionMet(queryKey, allPredicates, + false, + conditionCache); EXPECT_EQ(ConditionState::kFalse, conditionCache[0]); } @@ -399,8 +397,6 @@ TEST(SimpleConditionTrackerTest, TestSlicedCondition) { TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) { std::vector<sp<ConditionTracker>> allConditions; - vector<Matcher> dimensionInCondition; - std::unordered_set<HashableDimensionKey> dimensionKeys; SimplePredicate simplePredicate = getWakeLockHeldCondition( true /*nesting*/, true /*default to false*/, false /*slice output by uid*/, @@ -445,9 +441,9 @@ TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) { ConditionKey queryKey; conditionCache[0] = ConditionState::kNotEvaluated; - conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition, - true, true, - conditionCache, dimensionKeys); + conditionTracker.isConditionMet(queryKey, allPredicates, + true, + conditionCache); EXPECT_EQ(ConditionState::kTrue, conditionCache[0]); // another wake lock acquired by this uid @@ -489,10 +485,9 @@ TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) { // query again conditionCache[0] = ConditionState::kNotEvaluated; - dimensionKeys.clear(); - conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition, - true, true, - conditionCache, dimensionKeys); + conditionTracker.isConditionMet(queryKey, allPredicates, + true, + conditionCache); EXPECT_EQ(ConditionState::kFalse, conditionCache[0]); } @@ -500,8 +495,6 @@ TEST(SimpleConditionTrackerTest, TestStopAll) { std::vector<sp<ConditionTracker>> allConditions; for (Position position : { Position::FIRST, Position::LAST }) { - vector<Matcher> dimensionInCondition; - std::unordered_set<HashableDimensionKey> dimensionKeys; SimplePredicate simplePredicate = getWakeLockHeldCondition( true /*nesting*/, true /*default to false*/, true /*output slice by uid*/, position); @@ -555,9 +548,9 @@ TEST(SimpleConditionTrackerTest, TestStopAll) { const auto queryKey = getWakeLockQueryKey(position, uid_list1, conditionName); conditionCache[0] = ConditionState::kNotEvaluated; - conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition, - false, false, - conditionCache, dimensionKeys); + conditionTracker.isConditionMet(queryKey, allPredicates, + false, + conditionCache); EXPECT_EQ(ConditionState::kTrue, conditionCache[0]); // another wake lock acquired by uid2 @@ -594,9 +587,9 @@ TEST(SimpleConditionTrackerTest, TestStopAll) { // TEST QUERY const auto queryKey2 = getWakeLockQueryKey(position, uid_list2, conditionName); conditionCache[0] = ConditionState::kNotEvaluated; - conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition, - false, false, - conditionCache, dimensionKeys); + conditionTracker.isConditionMet(queryKey, allPredicates, + false, + conditionCache); EXPECT_EQ(ConditionState::kTrue, conditionCache[0]); @@ -628,17 +621,17 @@ TEST(SimpleConditionTrackerTest, TestStopAll) { // TEST QUERY const auto queryKey3 = getWakeLockQueryKey(position, uid_list1, conditionName); conditionCache[0] = ConditionState::kNotEvaluated; - conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition, - false, false, - conditionCache, dimensionKeys); + conditionTracker.isConditionMet(queryKey, allPredicates, + false, + conditionCache); EXPECT_EQ(ConditionState::kFalse, conditionCache[0]); // TEST QUERY const auto queryKey4 = getWakeLockQueryKey(position, uid_list2, conditionName); conditionCache[0] = ConditionState::kNotEvaluated; - conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition, - false, false, - conditionCache, dimensionKeys); + conditionTracker.isConditionMet(queryKey, allPredicates, + false, + conditionCache); EXPECT_EQ(ConditionState::kFalse, conditionCache[0]); } } diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp deleted file mode 100644 index e4186b7200a0..000000000000 --- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp +++ /dev/null @@ -1,961 +0,0 @@ -// Copyright (C) 2017 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include <gtest/gtest.h> - -#include "src/StatsLogProcessor.h" -#include "src/stats_log_util.h" -#include "tests/statsd_test_util.h" - -#include <vector> - -namespace android { -namespace os { -namespace statsd { - -#ifdef __ANDROID__ - -namespace { - -StatsdConfig CreateDurationMetricConfig_NoLink_AND_CombinationCondition( - DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition, - bool hashStringInReport) { - StatsdConfig config; - config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. - *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher(); - *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher(); - *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); - *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); - *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); - *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); - - auto scheduledJobPredicate = CreateScheduledJobPredicate(); - auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions(); - dimensions->set_field(android::util::SCHEDULED_JOB_STATE_CHANGED); - dimensions->add_child()->set_field(2); // job name field. - - auto screenIsOffPredicate = CreateScreenIsOffPredicate(); - - auto isSyncingPredicate = CreateIsSyncingPredicate(); - auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); - *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED, - {Position::FIRST}); - if (addExtraDimensionInCondition) { - syncDimension->add_child()->set_field(2 /* name field*/); - } - - config.set_hash_strings_in_metric_report(hashStringInReport); - *config.add_predicate() = scheduledJobPredicate; - *config.add_predicate() = screenIsOffPredicate; - *config.add_predicate() = isSyncingPredicate; - auto combinationPredicate = config.add_predicate(); - combinationPredicate->set_id(StringToId("CombinationPredicate")); - combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND); - addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); - addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate); - - auto metric = config.add_duration_metric(); - metric->set_bucket(FIVE_MINUTES); - metric->set_id(StringToId("scheduledJob")); - metric->set_what(scheduledJobPredicate.id()); - metric->set_condition(combinationPredicate->id()); - metric->set_aggregation_type(aggregationType); - auto dimensionWhat = metric->mutable_dimensions_in_what(); - dimensionWhat->set_field(android::util::SCHEDULED_JOB_STATE_CHANGED); - dimensionWhat->add_child()->set_field(2); // job name field. - *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions( - android::util::SYNC_STATE_CHANGED, {Position::FIRST}); - return config; -} - -} // namespace - -/* - The following test has the following input. - -{ 10000000002 10000000002 (8)9999[I], [S], job0[S], 1[I], } -{ 10000000010 10000000010 (7)111[I], App1[S], 222[I], GMSCoreModule1[S], 222[I], GMSCoreModule2[S], ReadEmail[S], 1[I], } -{ 10000000011 10000000011 (29)1[I], } -{ 10000000040 10000000040 (29)2[I], } -{ 10000000050 10000000050 (7)111[I], App1[S], 222[I], GMSCoreModule1[S], 222[I], GMSCoreModule2[S], ReadEmail[S], 0[I], } -{ 10000000101 10000000101 (8)9999[I], [S], job0[S], 0[I], } -{ 10000000102 10000000102 (29)1[I], } -{ 10000000200 10000000200 (7)111[I], App1[S], 222[I], GMSCoreModule1[S], 222[I], GMSCoreModule2[S], ReadEmail[S], 1[I], } -{ 10000000201 10000000201 (8)9999[I], [S], job2[S], 1[I], } -{ 10000000400 10000000400 (7)111[I], App1[S], 222[I], GMSCoreModule1[S], 222[I], GMSCoreModule2[S], ReadDoc[S], 1[I], } -{ 10000000401 10000000401 (7)333[I], App2[S], 222[I], GMSCoreModule1[S], 555[I], GMSCoreModule2[S], ReadEmail[S], 1[I], } -{ 10000000450 10000000450 (29)2[I], } -{ 10000000500 10000000500 (8)9999[I], [S], job2[S], 0[I], } -{ 10000000600 10000000600 (8)8888[I], [S], job2[S], 1[I], } -{ 10000000650 10000000650 (29)1[I], } -{ 309999999999 309999999999 (7)111[I], App1[S], 222[I], GMSCoreModule1[S], 222[I], GMSCoreModule2[S], ReadDoc[S], 0[I], } -{ 310000000100 310000000100 (29)2[I], } -{ 310000000300 310000000300 (7)111[I], App1[S], 222[I], GMSCoreModule1[S], 222[I], GMSCoreModule2[S], ReadEmail[S], 0[I], } -{ 310000000600 310000000600 (8)8888[I], [S], job1[S], 1[I], } -{ 310000000640 310000000640 (29)1[I], } -{ 310000000650 310000000650 (29)2[I], } -{ 310000000700 310000000700 (7)333[I], App2[S], 222[I], GMSCoreModule1[S], 555[I], GMSCoreModule2[S], ReadEmail[S], 0[I], } -{ 310000000850 310000000850 (8)8888[I], [S], job2[S], 0[I], } -{ 310000000900 310000000900 (8)8888[I], [S], job1[S], 0[I], } -*/ -TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_AND_CombinationCondition) { - for (const bool hashStringInReport : { true, false }) { - for (bool isDimensionInConditionSubSetOfConditionTrackerDimension : { true, false }) { - for (auto aggregationType : {DurationMetric::MAX_SPARSE, DurationMetric::SUM}) { - ConfigKey cfgKey; - auto config = CreateDurationMetricConfig_NoLink_AND_CombinationCondition( - aggregationType, isDimensionInConditionSubSetOfConditionTrackerDimension, - hashStringInReport); - int64_t bucketStartTimeNs = 10000000000; - int64_t bucketSizeNs = - TimeUnitToBucketSizeInMillis( - config.duration_metric(0).bucket()) * 1000000LL; - - auto processor = CreateStatsLogProcessor( - bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); - EXPECT_EQ(processor->mMetricsManagers.size(), 1u); - EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - - std::vector<AttributionNodeInternal> attributions1 = { - CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; - - std::vector<AttributionNodeInternal> attributions2 = { - CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; - - std::vector<std::unique_ptr<LogEvent>> events; - - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 11)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + 40)); - - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 102)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + 450)); - - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 650)); - events.push_back(CreateScreenStateChangedEvent( - android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + bucketSizeNs + 100)); - - events.push_back(CreateScreenStateChangedEvent( - android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + bucketSizeNs + 640)); - events.push_back(CreateScreenStateChangedEvent( - android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + bucketSizeNs + 650)); - - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(9999, "")}, "job0", bucketStartTimeNs + 2)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(9999, "")}, "job0",bucketStartTimeNs + 101)); - - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(9999, "")}, "job2", bucketStartTimeNs + 201)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(9999, "")}, "job2",bucketStartTimeNs + 500)); - - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(8888, "")}, "job2", bucketStartTimeNs + 600)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(8888, "")}, "job2", - bucketStartTimeNs + bucketSizeNs + 850)); - - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(8888, "")}, "job1", - bucketStartTimeNs + bucketSizeNs + 600)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(8888, "")}, "job1", - bucketStartTimeNs + bucketSizeNs + 900)); - - events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 10)); - events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 50)); - - events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 200)); - events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", - bucketStartTimeNs + bucketSizeNs + 300)); - - events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", - bucketStartTimeNs + 400)); - events.push_back(CreateSyncEndEvent(attributions1, "ReadDoc", - bucketStartTimeNs + bucketSizeNs - 1)); - - events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", - bucketStartTimeNs + 401)); - events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", - bucketStartTimeNs + bucketSizeNs + 700)); - - sortLogEventsByTimestamp(&events); - - for (const auto& event : events) { - processor->OnLogEvent(event.get()); - } - - ConfigMetricsReportList reports; - vector<uint8_t> buffer; - processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, - true, ADB_DUMP, FAST, &buffer); - EXPECT_TRUE(buffer.size() > 0); - EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); - backfillDimensionPath(&reports); - backfillStringInReport(&reports); - backfillStartEndTimestamp(&reports); - - EXPECT_EQ(reports.reports_size(), 1); - EXPECT_EQ(reports.reports(0).metrics_size(), 1); - StatsLogReport::DurationMetricDataWrapper metrics; - sortMetricDataByDimensionsValue( - reports.reports(0).metrics(0).duration_metrics(), &metrics); - if (aggregationType == DurationMetric::SUM) { - EXPECT_EQ(metrics.data_size(), 4); - auto data = metrics.data(0); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple(). - dimensions_value(0).value_str(), - "job0"); // job name - ValidateAttributionUidAndTagDimension( - data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 111, "App1"); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 40 - 11); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - - - data = metrics.data(1); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple(). - dimensions_value(0).value_str(), - "job1"); // job name - ValidateAttributionUidAndTagDimension( - data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 333, "App2"); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 10); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(2); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple(). - dimensions_value(0).value_str(), - "job2"); // job name - ValidateAttributionUidAndTagDimension( - data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 111, "App1"); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 201 + bucketSizeNs - 650); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(3); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple(). - dimensions_value(0).value_str(), - "job2"); // job name - ValidateAttributionUidAndTagDimension( - data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 333, "App2"); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 401 + bucketSizeNs - 650); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100 + 650 - 640); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } else { - EXPECT_EQ(metrics.data_size(), 4); - auto data = metrics.data(0); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple(). - dimensions_value(0).value_str(), - "job0"); // job name - ValidateAttributionUidAndTagDimension( - data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 111, "App1"); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 40 - 11); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - - data = metrics.data(1); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple(). - dimensions_value(0).value_str(), - "job1"); // job name - ValidateAttributionUidAndTagDimension( - data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 333, "App2"); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 10); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(2); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job2"); // job name - ValidateAttributionUidAndTagDimension( - data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 111, "App1"); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 201); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 650 + 100); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(3); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple(). - dimensions_value(0).value_str(), - "job2"); // job name - ValidateAttributionUidAndTagDimension( - data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 333, "App2"); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 401); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 650 + 110); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } - } - } - } -} - -namespace { - -StatsdConfig CreateDurationMetricConfig_Link_AND_CombinationCondition( - DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition) { - StatsdConfig config; - config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. - *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher(); - *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher(); - *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); - *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); - *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); - *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); - - auto scheduledJobPredicate = CreateScheduledJobPredicate(); - auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions(); - *dimensions = CreateAttributionUidDimensions( - android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); - dimensions->add_child()->set_field(2); // job name field. - - auto isSyncingPredicate = CreateIsSyncingPredicate(); - auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); - *syncDimension = CreateAttributionUidDimensions( - android::util::SYNC_STATE_CHANGED, {Position::FIRST}); - if (addExtraDimensionInCondition) { - syncDimension->add_child()->set_field(2 /* name field*/); - } - - auto screenIsOffPredicate = CreateScreenIsOffPredicate(); - - *config.add_predicate() = scheduledJobPredicate; - *config.add_predicate() = screenIsOffPredicate; - *config.add_predicate() = isSyncingPredicate; - auto combinationPredicate = config.add_predicate(); - combinationPredicate->set_id(StringToId("CombinationPredicate")); - combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND); - addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); - addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate); - - auto metric = config.add_duration_metric(); - metric->set_bucket(FIVE_MINUTES); - metric->set_id(StringToId("scheduledJob")); - metric->set_what(scheduledJobPredicate.id()); - metric->set_condition(combinationPredicate->id()); - metric->set_aggregation_type(aggregationType); - *metric->mutable_dimensions_in_what() = CreateAttributionUidDimensions( - android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); - - auto links = metric->add_links(); - links->set_condition(isSyncingPredicate.id()); - *links->mutable_fields_in_what() = - CreateAttributionUidDimensions( - android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); - *links->mutable_fields_in_condition() = - CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST}); - return config; -} - -} // namespace - -TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_AND_CombinationCondition) { - for (bool isFullLink : {true, false}) { - for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) { - ConfigKey cfgKey; - auto config = CreateDurationMetricConfig_Link_AND_CombinationCondition( - aggregationType, !isFullLink); - int64_t bucketStartTimeNs = 10000000000; - int64_t bucketSizeNs = - TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; - - auto processor = CreateStatsLogProcessor( - bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); - EXPECT_EQ(processor->mMetricsManagers.size(), 1u); - EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - - std::vector<AttributionNodeInternal> attributions1 = { - CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; - - std::vector<AttributionNodeInternal> attributions2 = { - CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; - - std::vector<AttributionNodeInternal> attributions3 = { - CreateAttribution(444, "App3"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; - - std::vector<std::unique_ptr<LogEvent>> events; - - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 55)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + 120)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 121)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + 450)); - - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 501)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + bucketSizeNs + 100)); - - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(111, "App1")}, "job1", bucketStartTimeNs + 1)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(111, "App1")}, "job1",bucketStartTimeNs + 101)); - - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 201)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2",bucketStartTimeNs + 500)); - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 600)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2", - bucketStartTimeNs + bucketSizeNs + 850)); - - events.push_back( - CreateStartScheduledJobEvent({CreateAttribution(444, "App3")}, "job3", - bucketStartTimeNs + bucketSizeNs - 2)); - events.push_back( - CreateFinishScheduledJobEvent({CreateAttribution(444, "App3")}, "job3", - bucketStartTimeNs + bucketSizeNs + 900)); - - events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 50)); - events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 110)); - - events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", - bucketStartTimeNs + 300)); - events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", - bucketStartTimeNs + bucketSizeNs + 700)); - events.push_back(CreateSyncStartEvent(attributions2, "ReadDoc", - bucketStartTimeNs + 400)); - events.push_back(CreateSyncEndEvent(attributions2, "ReadDoc", - bucketStartTimeNs + bucketSizeNs - 1)); - - events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc", - bucketStartTimeNs + 550)); - events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc", - bucketStartTimeNs + 800)); - events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc", - bucketStartTimeNs + bucketSizeNs - 1)); - events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc", - bucketStartTimeNs + bucketSizeNs + 700)); - - sortLogEventsByTimestamp(&events); - - for (const auto& event : events) { - processor->OnLogEvent(event.get()); - } - - ConfigMetricsReportList reports; - vector<uint8_t> buffer; - processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, - true, ADB_DUMP, FAST, &buffer); - EXPECT_TRUE(buffer.size() > 0); - EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); - backfillDimensionPath(&reports); - backfillStringInReport(&reports); - backfillStartEndTimestamp(&reports); - - EXPECT_EQ(reports.reports_size(), 1); - EXPECT_EQ(reports.reports(0).metrics_size(), 1); - StatsLogReport::DurationMetricDataWrapper metrics; - sortMetricDataByDimensionsValue( - reports.reports(0).metrics(0).duration_metrics(), &metrics); - - if (aggregationType == DurationMetric::SUM) { - EXPECT_EQ(metrics.data_size(), 3); - auto data = metrics.data(0); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 55); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - - data = metrics.data(1); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 300 + bucketSizeNs - 600); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(2); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } else { - EXPECT_EQ(metrics.data_size(), 3); - auto data = metrics.data(0); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 55); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - - data = metrics.data(1); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 300); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 100); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(2); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } - } - } -} - -namespace { - -StatsdConfig CreateDurationMetricConfig_PartialLink_AND_CombinationCondition( - DurationMetric::AggregationType aggregationType, bool hashStringInReport) { - StatsdConfig config; - config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. - *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher(); - *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher(); - *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); - *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); - *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); - *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); - - auto scheduledJobPredicate = CreateScheduledJobPredicate(); - auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions(); - *dimensions = CreateAttributionUidDimensions( - android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); - dimensions->add_child()->set_field(2); // job name field. - - auto isSyncingPredicate = CreateIsSyncingPredicate(); - auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); - *syncDimension = CreateAttributionUidDimensions( - android::util::SYNC_STATE_CHANGED, {Position::FIRST}); - syncDimension->add_child()->set_field(2 /* name field*/); - - auto screenIsOffPredicate = CreateScreenIsOffPredicate(); - - config.set_hash_strings_in_metric_report(hashStringInReport); - *config.add_predicate() = scheduledJobPredicate; - *config.add_predicate() = screenIsOffPredicate; - *config.add_predicate() = isSyncingPredicate; - auto combinationPredicate = config.add_predicate(); - combinationPredicate->set_id(StringToId("CombinationPredicate")); - combinationPredicate->mutable_combination()->set_operation(LogicalOperation::AND); - addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); - addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate); - - auto metric = config.add_duration_metric(); - metric->set_bucket(FIVE_MINUTES); - metric->set_id(StringToId("scheduledJob")); - metric->set_what(scheduledJobPredicate.id()); - metric->set_condition(combinationPredicate->id()); - metric->set_aggregation_type(aggregationType); - *metric->mutable_dimensions_in_what() = CreateAttributionUidDimensions( - android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); - *metric->mutable_dimensions_in_condition() = *syncDimension; - - - auto links = metric->add_links(); - links->set_condition(isSyncingPredicate.id()); - *links->mutable_fields_in_what() = - CreateAttributionUidDimensions( - android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); - *links->mutable_fields_in_condition() = - CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST}); - return config; -} - -} // namespace - -TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_AND_CombinationCondition) { - for (const bool hashStringInReport : {true, false}) { - for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) { - ConfigKey cfgKey; - auto config = - CreateDurationMetricConfig_PartialLink_AND_CombinationCondition( - aggregationType, hashStringInReport); - int64_t bucketStartTimeNs = 10000000000; - int64_t bucketSizeNs = - TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; - - auto processor = CreateStatsLogProcessor( - bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); - EXPECT_EQ(processor->mMetricsManagers.size(), 1u); - EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - - std::vector<AttributionNodeInternal> attributions1 = { - CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; - - std::vector<AttributionNodeInternal> attributions2 = { - CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; - - std::vector<AttributionNodeInternal> attributions3 = { - CreateAttribution(444, "App3"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; - - std::vector<std::unique_ptr<LogEvent>> events; - - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 55)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + 120)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 121)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + 450)); - - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 501)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + bucketSizeNs + 100)); - - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(111, "App1")}, "job1", bucketStartTimeNs + 1)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(111, "App1")}, "job1",bucketStartTimeNs + 101)); - - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 201)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2",bucketStartTimeNs + 500)); - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 600)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2", - bucketStartTimeNs + bucketSizeNs + 850)); - - events.push_back( - CreateStartScheduledJobEvent({CreateAttribution(444, "App3")}, "job3", - bucketStartTimeNs + bucketSizeNs - 2)); - events.push_back( - CreateFinishScheduledJobEvent({CreateAttribution(444, "App3")}, "job3", - bucketStartTimeNs + bucketSizeNs + 900)); - - events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 50)); - events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 110)); - - events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", - bucketStartTimeNs + 300)); - events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", - bucketStartTimeNs + bucketSizeNs + 700)); - events.push_back(CreateSyncStartEvent(attributions2, "ReadDoc", - bucketStartTimeNs + 400)); - events.push_back(CreateSyncEndEvent(attributions2, "ReadDoc", - bucketStartTimeNs + bucketSizeNs - 1)); - - events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc", - bucketStartTimeNs + 550)); - events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc", - bucketStartTimeNs + 800)); - events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc", - bucketStartTimeNs + bucketSizeNs - 1)); - events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc", - bucketStartTimeNs + bucketSizeNs + 700)); - - sortLogEventsByTimestamp(&events); - - for (const auto& event : events) { - processor->OnLogEvent(event.get()); - } - - ConfigMetricsReportList reports; - vector<uint8_t> buffer; - processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, - true, ADB_DUMP, FAST, &buffer); - EXPECT_TRUE(buffer.size() > 0); - EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); - backfillDimensionPath(&reports); - backfillStringInReport(&reports); - backfillStartEndTimestamp(&reports); - - EXPECT_EQ(reports.reports_size(), 1); - EXPECT_EQ(reports.reports(0).metrics_size(), 1); - StatsLogReport::DurationMetricDataWrapper metrics; - sortMetricDataByDimensionsValue( - reports.reports(0).metrics(0).duration_metrics(), &metrics); - if (aggregationType == DurationMetric::SUM) { - EXPECT_EQ(metrics.data_size(), 4); - auto data = metrics.data(0); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111); - EXPECT_EQ("ReadEmail", - data.dimensions_in_condition().value_tuple(). - dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 55); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - - data = metrics.data(1); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333); - EXPECT_EQ("ReadDoc", - data.dimensions_in_condition().value_tuple(). - dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 1 - 600 + 50); - - data = metrics.data(2); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333); - EXPECT_EQ("ReadEmail", - data.dimensions_in_condition().value_tuple(). - dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 300 + bucketSizeNs - 600); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(3); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 444); - EXPECT_EQ("ReadDoc", - data.dimensions_in_condition().value_tuple(). - dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } else { - EXPECT_EQ(metrics.data_size(), 4); - auto data = metrics.data(0); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111); - EXPECT_EQ("ReadEmail", - data.dimensions_in_condition().value_tuple(). - dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 55); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - - data = metrics.data(1); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333); - EXPECT_EQ("ReadDoc", - data.dimensions_in_condition().value_tuple(). - dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 50); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 1 - 600); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(2); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333); - EXPECT_EQ("ReadEmail", - data.dimensions_in_condition().value_tuple(). - dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 300); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 100); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(3); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 444); - EXPECT_EQ("ReadDoc", - data.dimensions_in_condition().value_tuple(). - dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } - } - } -} - -#else -GTEST_LOG_(INFO) << "This test does nothing.\n"; -#endif - -} // namespace statsd -} // namespace os -} // namespace android diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp deleted file mode 100644 index f3ecd56dd946..000000000000 --- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp +++ /dev/null @@ -1,816 +0,0 @@ -// Copyright (C) 2017 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include <gtest/gtest.h> - -#include "src/StatsLogProcessor.h" -#include "src/stats_log_util.h" -#include "tests/statsd_test_util.h" - -#include <vector> - -namespace android { -namespace os { -namespace statsd { - -#ifdef __ANDROID__ - -namespace { - -StatsdConfig CreateCountMetric_NoLink_CombinationCondition_Config() { - StatsdConfig config; - config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. - auto screenBrightnessChangeAtomMatcher = CreateScreenBrightnessChangedAtomMatcher(); - *config.add_atom_matcher() = screenBrightnessChangeAtomMatcher; - *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); - *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); - *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher(); - *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher(); - - auto screenIsOffPredicate = CreateScreenIsOffPredicate(); - *config.add_predicate() = screenIsOffPredicate; - - auto holdingWakelockPredicate = CreateHoldingWakelockPredicate(); - // The predicate is dimensioning by any attribution node and both by uid and tag. - *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = - CreateAttributionUidAndTagDimensions(android::util::WAKELOCK_STATE_CHANGED, - {Position::FIRST}); - *config.add_predicate() = holdingWakelockPredicate; - - auto combinationPredicate = config.add_predicate(); - combinationPredicate->set_id(987654); - combinationPredicate->mutable_combination()->set_operation(LogicalOperation::OR); - addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); - addPredicateToPredicateCombination(holdingWakelockPredicate, combinationPredicate); - - auto metric = config.add_count_metric(); - metric->set_id(StringToId("ScreenBrightnessChangeMetric")); - metric->set_what(screenBrightnessChangeAtomMatcher.id()); - metric->set_condition(combinationPredicate->id()); - *metric->mutable_dimensions_in_what() = - CreateDimensions(android::util::SCREEN_BRIGHTNESS_CHANGED, {1 /* level */}); - *metric->mutable_dimensions_in_condition() = CreateAttributionUidDimensions( - android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST}); - metric->set_bucket(FIVE_MINUTES); - return config; -} - -} // namespace - -TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition) { - ConfigKey cfgKey; - auto config = CreateCountMetric_NoLink_CombinationCondition_Config(); - int64_t bucketStartTimeNs = 10000000000; - int64_t bucketSizeNs = - TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL; - - auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); - EXPECT_EQ(processor->mMetricsManagers.size(), 1u); - EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - - std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"), - CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; - - std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(333, "App2"), - CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; - - std::vector<std::unique_ptr<LogEvent>> events; - events.push_back( - CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 100)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + bucketSizeNs + 1)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 2 * bucketSizeNs - 10)); - - events.push_back(CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 200)); - events.push_back( - CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1)); - - events.push_back(CreateAcquireWakelockEvent(attributions2, "wl2", - bucketStartTimeNs + bucketSizeNs - 100)); - events.push_back(CreateReleaseWakelockEvent(attributions2, "wl2", - bucketStartTimeNs + 2 * bucketSizeNs - 50)); - - events.push_back(CreateScreenBrightnessChangedEvent(123, bucketStartTimeNs + 11)); - events.push_back(CreateScreenBrightnessChangedEvent(123, bucketStartTimeNs + 101)); - events.push_back(CreateScreenBrightnessChangedEvent(123, bucketStartTimeNs + 201)); - events.push_back(CreateScreenBrightnessChangedEvent(456, bucketStartTimeNs + 203)); - events.push_back( - CreateScreenBrightnessChangedEvent(456, bucketStartTimeNs + bucketSizeNs - 99)); - events.push_back(CreateScreenBrightnessChangedEvent(456, bucketStartTimeNs + bucketSizeNs - 2)); - events.push_back(CreateScreenBrightnessChangedEvent(789, bucketStartTimeNs + bucketSizeNs - 1)); - events.push_back(CreateScreenBrightnessChangedEvent(456, bucketStartTimeNs + bucketSizeNs + 2)); - events.push_back( - CreateScreenBrightnessChangedEvent(789, bucketStartTimeNs + 2 * bucketSizeNs - 11)); - events.push_back( - CreateScreenBrightnessChangedEvent(789, bucketStartTimeNs + 2 * bucketSizeNs - 9)); - events.push_back( - CreateScreenBrightnessChangedEvent(789, bucketStartTimeNs + 2 * bucketSizeNs - 1)); - - sortLogEventsByTimestamp(&events); - - for (const auto& event : events) { - processor->OnLogEvent(event.get()); - } - - ConfigMetricsReportList reports; - vector<uint8_t> buffer; - processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true, - ADB_DUMP, FAST, &buffer); - EXPECT_TRUE(buffer.size() > 0); - EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); - backfillDimensionPath(&reports); - backfillStringInReport(&reports); - backfillStartEndTimestamp(&reports); - - EXPECT_EQ(reports.reports_size(), 1); - EXPECT_EQ(reports.reports(0).metrics_size(), 1); - StatsLogReport::CountMetricDataWrapper countMetrics; - sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics); - - EXPECT_EQ(countMetrics.data_size(), 7); - auto data = countMetrics.data(0); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 123); - EXPECT_FALSE(data.dimensions_in_condition().has_field()); - - data = countMetrics.data(1); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 123); - ValidateAttributionUidDimension(data.dimensions_in_condition(), - android::util::WAKELOCK_STATE_CHANGED, 111); - - data = countMetrics.data(2); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).count(), 3); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 456); - ValidateAttributionUidDimension(data.dimensions_in_condition(), - android::util::WAKELOCK_STATE_CHANGED, 111); - - data = countMetrics.data(3); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).count(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).count(), 1); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); - EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 456); - ValidateAttributionUidDimension(data.dimensions_in_condition(), - android::util::WAKELOCK_STATE_CHANGED, 333); - - data = countMetrics.data(4); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).count(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); - EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 789); - EXPECT_FALSE(data.dimensions_in_condition().has_field()); - - data = countMetrics.data(5); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 789); - ValidateAttributionUidDimension(data.dimensions_in_condition(), - android::util::WAKELOCK_STATE_CHANGED, 111); - - data = countMetrics.data(6); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 789); - ValidateAttributionUidDimension(data.dimensions_in_condition(), - android::util::WAKELOCK_STATE_CHANGED, 333); -} - -namespace { - -StatsdConfig CreateCountMetric_Link_CombinationCondition() { - StatsdConfig config; - config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. - auto appCrashMatcher = CreateProcessCrashAtomMatcher(); - *config.add_atom_matcher() = appCrashMatcher; - *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); - *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); - *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); - *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); - - auto screenIsOffPredicate = CreateScreenIsOffPredicate(); - auto isSyncingPredicate = CreateIsSyncingPredicate(); - auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); - *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED, - {Position::FIRST}); - syncDimension->add_child()->set_field(2 /* name field*/); - - *config.add_predicate() = screenIsOffPredicate; - *config.add_predicate() = isSyncingPredicate; - auto combinationPredicate = config.add_predicate(); - combinationPredicate->set_id(987654); - combinationPredicate->mutable_combination()->set_operation(LogicalOperation::OR); - addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); - addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate); - - auto metric = config.add_count_metric(); - metric->set_bucket(FIVE_MINUTES); - metric->set_id(StringToId("AppCrashMetric")); - metric->set_what(appCrashMatcher.id()); - metric->set_condition(combinationPredicate->id()); - *metric->mutable_dimensions_in_what() = - CreateDimensions(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, {1 /* uid */}); - *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions( - android::util::SYNC_STATE_CHANGED, {Position::FIRST}); - - // Links between crash atom and condition of app is in syncing. - auto links = metric->add_links(); - links->set_condition(isSyncingPredicate.id()); - auto dimensionWhat = links->mutable_fields_in_what(); - dimensionWhat->set_field(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); - dimensionWhat->add_child()->set_field(1); // uid field. - *links->mutable_fields_in_condition() = - CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST}); - return config; -} - -} // namespace - -TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition) { - ConfigKey cfgKey; - auto config = CreateCountMetric_Link_CombinationCondition(); - int64_t bucketStartTimeNs = 10000000000; - int64_t bucketSizeNs = - TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL; - - auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); - EXPECT_EQ(processor->mMetricsManagers.size(), 1u); - EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"), - CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; - - std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(333, "App2"), - CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; - - std::vector<std::unique_ptr<LogEvent>> events; - - events.push_back(CreateAppCrashEvent(111, bucketStartTimeNs + 11)); - events.push_back(CreateAppCrashEvent(111, bucketStartTimeNs + 101)); - events.push_back(CreateAppCrashEvent(222, bucketStartTimeNs + 101)); - - events.push_back(CreateAppCrashEvent(222, bucketStartTimeNs + 201)); - events.push_back(CreateAppCrashEvent(111, bucketStartTimeNs + 211)); - events.push_back(CreateAppCrashEvent(333, bucketStartTimeNs + 211)); - - events.push_back(CreateAppCrashEvent(111, bucketStartTimeNs + 401)); - events.push_back(CreateAppCrashEvent(333, bucketStartTimeNs + 401)); - events.push_back(CreateAppCrashEvent(555, bucketStartTimeNs + 401)); - - events.push_back(CreateAppCrashEvent(111, bucketStartTimeNs + bucketSizeNs + 301)); - events.push_back(CreateAppCrashEvent(333, bucketStartTimeNs + bucketSizeNs + 301)); - - events.push_back(CreateAppCrashEvent(777, bucketStartTimeNs + bucketSizeNs + 701)); - - events.push_back( - CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 100)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + 202)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + bucketSizeNs + 700)); - - events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", bucketStartTimeNs + 200)); - events.push_back( - CreateSyncEndEvent(attributions1, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300)); - - events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", bucketStartTimeNs + 400)); - events.push_back( - CreateSyncEndEvent(attributions1, "ReadDoc", bucketStartTimeNs + bucketSizeNs - 1)); - - events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", bucketStartTimeNs + 400)); - events.push_back( - CreateSyncEndEvent(attributions2, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 600)); - - sortLogEventsByTimestamp(&events); - - for (const auto& event : events) { - processor->OnLogEvent(event.get()); - } - - ConfigMetricsReportList reports; - vector<uint8_t> buffer; - processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true, - ADB_DUMP, FAST, &buffer); - EXPECT_TRUE(buffer.size() > 0); - EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); - backfillDimensionPath(&reports); - backfillStringInReport(&reports); - backfillStartEndTimestamp(&reports); - - EXPECT_EQ(reports.reports_size(), 1); - EXPECT_EQ(reports.reports(0).metrics_size(), 1); - StatsLogReport::CountMetricDataWrapper countMetrics; - sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics); - - EXPECT_EQ(countMetrics.data_size(), 5); - auto data = countMetrics.data(0); - EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 111); - EXPECT_FALSE(data.dimensions_in_condition().has_field()); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); - - data = countMetrics.data(1); - EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 111); - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 111, "App1"); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).count(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); - - data = countMetrics.data(2); - EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 222); - EXPECT_FALSE(data.dimensions_in_condition().has_field()); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).count(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); - - data = countMetrics.data(3); - EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 333); - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 333, "App2"); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).count(), 1); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); - - data = countMetrics.data(4); - EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 777); - EXPECT_FALSE(data.dimensions_in_condition().has_field()); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); -} - -namespace { - -StatsdConfig CreateDurationMetricConfig_NoLink_CombinationCondition( - DurationMetric::AggregationType aggregationType) { - StatsdConfig config; - config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. - *config.add_atom_matcher() = CreateBatterySaverModeStartAtomMatcher(); - *config.add_atom_matcher() = CreateBatterySaverModeStopAtomMatcher(); - *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); - *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); - *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); - *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); - - auto inBatterySaverModePredicate = CreateBatterySaverModePredicate(); - - auto screenIsOffPredicate = CreateScreenIsOffPredicate(); - auto isSyncingPredicate = CreateIsSyncingPredicate(); - auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); - *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED, - {Position::FIRST}); - syncDimension->add_child()->set_field(2 /* name field */); - - *config.add_predicate() = inBatterySaverModePredicate; - *config.add_predicate() = screenIsOffPredicate; - *config.add_predicate() = isSyncingPredicate; - auto combinationPredicate = config.add_predicate(); - combinationPredicate->set_id(987654); - combinationPredicate->mutable_combination()->set_operation(LogicalOperation::OR); - addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); - addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate); - - auto metric = config.add_duration_metric(); - metric->set_bucket(FIVE_MINUTES); - metric->set_id(StringToId("BatterySaverModeDurationMetric")); - metric->set_what(inBatterySaverModePredicate.id()); - metric->set_condition(combinationPredicate->id()); - metric->set_aggregation_type(aggregationType); - *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions( - android::util::SYNC_STATE_CHANGED, {Position::FIRST}); - return config; -} - -} // namespace - -TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_OR_CombinationCondition) { - for (auto aggregationType : { DurationMetric::MAX_SPARSE, DurationMetric::SUM}) { - ConfigKey cfgKey; - auto config = CreateDurationMetricConfig_NoLink_CombinationCondition(aggregationType); - int64_t bucketStartTimeNs = 10000000000; - int64_t bucketSizeNs = - TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; - - auto processor = CreateStatsLogProcessor( - bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); - EXPECT_EQ(processor->mMetricsManagers.size(), 1u); - EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - - std::vector<AttributionNodeInternal> attributions1 = { - CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; - - std::vector<AttributionNodeInternal> attributions2 = { - CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; - - std::vector<std::unique_ptr<LogEvent>> events; - - events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 1)); - events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 101)); - events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 110)); - - events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 201)); - events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 500)); - - events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 600)); - events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + bucketSizeNs + 850)); - - events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + bucketSizeNs + 870)); - events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + bucketSizeNs + 900)); - - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + 10)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 100)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + 202)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + bucketSizeNs + 800)); - - events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", bucketStartTimeNs + 200)); - events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", - bucketStartTimeNs + bucketSizeNs + 300)); - - events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", bucketStartTimeNs + 400)); - events.push_back( - CreateSyncEndEvent(attributions1, "ReadDoc", bucketStartTimeNs + bucketSizeNs - 1)); - - events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", bucketStartTimeNs + 401)); - events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", - bucketStartTimeNs + bucketSizeNs + 700)); - - sortLogEventsByTimestamp(&events); - - for (const auto& event : events) { - processor->OnLogEvent(event.get()); - } - - ConfigMetricsReportList reports; - vector<uint8_t> buffer; - processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true, - ADB_DUMP, FAST, &buffer); - EXPECT_TRUE(buffer.size() > 0); - EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); - backfillDimensionPath(&reports); - backfillStringInReport(&reports); - backfillStartEndTimestamp(&reports); - - EXPECT_EQ(reports.reports_size(), 1); - EXPECT_EQ(reports.reports(0).metrics_size(), 1); - StatsLogReport::DurationMetricDataWrapper metrics; - sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(), &metrics); - - EXPECT_EQ(metrics.data_size(), 3); - auto data = metrics.data(0); - EXPECT_FALSE(data.dimensions_in_what().has_field()); - EXPECT_FALSE(data.dimensions_in_condition().has_field()); - if (aggregationType == DurationMetric::SUM) { - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 9); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 30); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } else { - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 9); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 30); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } - - data = metrics.data(1); - EXPECT_FALSE(data.dimensions_in_what().has_field()); - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 111, "App1"); - EXPECT_EQ(data.bucket_info_size(), 2); - - if (aggregationType == DurationMetric::SUM) { - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 201 + bucketSizeNs - 600); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 300); - } else { - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 201); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 300); - } - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(2); - EXPECT_FALSE(data.dimensions_in_what().has_field()); - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 333, "App2"); - EXPECT_EQ(data.bucket_info_size(), 2); - if (aggregationType == DurationMetric::SUM) { - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 401 + bucketSizeNs - 600); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700); - } else { - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 401); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs + 700 - 600); - } - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } -} - -namespace { - -StatsdConfig CreateDurationMetricConfig_Link_CombinationCondition( - DurationMetric::AggregationType aggregationType) { - StatsdConfig config; - config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. - *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher(); - *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher(); - *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); - *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); - *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); - *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); - - auto screenIsOffPredicate = CreateScreenIsOffPredicate(); - auto isSyncingPredicate = CreateIsSyncingPredicate(); - auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); - *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED, - {Position::FIRST}); - syncDimension->add_child()->set_field(2 /* name field */); - - auto isInBackgroundPredicate = CreateIsInBackgroundPredicate(); - *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() = - CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */}); - - *config.add_predicate() = screenIsOffPredicate; - *config.add_predicate() = isSyncingPredicate; - *config.add_predicate() = isInBackgroundPredicate; - auto combinationPredicate = config.add_predicate(); - combinationPredicate->set_id(987654); - combinationPredicate->mutable_combination()->set_operation(LogicalOperation::OR); - addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); - addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate); - - auto metric = config.add_duration_metric(); - metric->set_bucket(FIVE_MINUTES); - metric->set_id(StringToId("AppInBackgroundMetric")); - metric->set_what(isInBackgroundPredicate.id()); - metric->set_condition(combinationPredicate->id()); - metric->set_aggregation_type(aggregationType); - *metric->mutable_dimensions_in_what() = - CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */}); - *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions( - android::util::SYNC_STATE_CHANGED, {Position::FIRST}); - - // Links between crash atom and condition of app is in syncing. - auto links = metric->add_links(); - links->set_condition(isSyncingPredicate.id()); - auto dimensionWhat = links->mutable_fields_in_what(); - dimensionWhat->set_field(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED); - dimensionWhat->add_child()->set_field(1); // uid field. - *links->mutable_fields_in_condition() = - CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST}); - return config; -} - -} // namespace - -TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_OR_CombinationCondition) { - for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) { - ConfigKey cfgKey; - auto config = CreateDurationMetricConfig_Link_CombinationCondition(aggregationType); - int64_t bucketStartTimeNs = 10000000000; - int64_t bucketSizeNs = - TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; - - auto processor = CreateStatsLogProcessor( - bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); - EXPECT_EQ(processor->mMetricsManagers.size(), 1u); - EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - - std::vector<AttributionNodeInternal> attributions1 = { - CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; - - std::vector<AttributionNodeInternal> attributions2 = { - CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; - - std::vector<std::unique_ptr<LogEvent>> events; - - events.push_back(CreateMoveToBackgroundEvent(111, bucketStartTimeNs + 101)); - events.push_back(CreateMoveToForegroundEvent(111, bucketStartTimeNs + 110)); - - events.push_back(CreateMoveToBackgroundEvent(111, bucketStartTimeNs + 201)); - events.push_back(CreateMoveToForegroundEvent(111, bucketStartTimeNs + bucketSizeNs + 100)); - - events.push_back(CreateMoveToBackgroundEvent(333, bucketStartTimeNs + 399)); - events.push_back(CreateMoveToForegroundEvent(333, bucketStartTimeNs + bucketSizeNs + 800)); - - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + 10)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 100)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + 202)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + bucketSizeNs + 801)); - - events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", bucketStartTimeNs + 200)); - events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", - bucketStartTimeNs + bucketSizeNs + 300)); - - events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", bucketStartTimeNs + 400)); - events.push_back( - CreateSyncEndEvent(attributions1, "ReadDoc", bucketStartTimeNs + bucketSizeNs - 1)); - - events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", bucketStartTimeNs + 401)); - events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", - bucketStartTimeNs + bucketSizeNs + 700)); - - sortLogEventsByTimestamp(&events); - - for (const auto& event : events) { - processor->OnLogEvent(event.get()); - } - - ConfigMetricsReportList reports; - vector<uint8_t> buffer; - processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true, - ADB_DUMP, FAST, &buffer); - EXPECT_TRUE(buffer.size() > 0); - EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); - backfillDimensionPath(&reports); - backfillStringInReport(&reports); - backfillStartEndTimestamp(&reports); - - EXPECT_EQ(reports.reports_size(), 1); - EXPECT_EQ(reports.reports(0).metrics_size(), 1); - StatsLogReport::DurationMetricDataWrapper metrics; - sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(), &metrics); - - EXPECT_EQ(metrics.data_size(), 3); - auto data = metrics.data(0); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 111); - EXPECT_FALSE(data.dimensions_in_condition().has_field()); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 9); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); - - data = metrics.data(1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 111); - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 111, "App1"); - if (aggregationType == DurationMetric::SUM) { - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 201); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } else { - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs + 100 - 201); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } - - data = metrics.data(2); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 333); - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 333, "App2"); - if (aggregationType == DurationMetric::SUM) { - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 401); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } else { - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs + 299); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } - } -} - -#else -GTEST_LOG_(INFO) << "This test does nothing.\n"; -#endif - -} // namespace statsd -} // namespace os -} // namespace android diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp deleted file mode 100644 index 489bb0b21a2e..000000000000 --- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp +++ /dev/null @@ -1,814 +0,0 @@ -// Copyright (C) 2017 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include <gtest/gtest.h> - -#include "src/StatsLogProcessor.h" -#include "src/stats_log_util.h" -#include "tests/statsd_test_util.h" - -#include <vector> - -namespace android { -namespace os { -namespace statsd { - -#ifdef __ANDROID__ - -namespace { - -StatsdConfig CreateDurationMetricConfig_NoLink_SimpleCondition( - DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition) { - StatsdConfig config; - config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. - *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher(); - *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher(); - *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); - *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); - - auto scheduledJobPredicate = CreateScheduledJobPredicate(); - auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions(); - dimensions->set_field(android::util::SCHEDULED_JOB_STATE_CHANGED); - dimensions->add_child()->set_field(2); // job name field. - - auto isSyncingPredicate = CreateIsSyncingPredicate(); - auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); - *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED, - {Position::FIRST}); - if (addExtraDimensionInCondition) { - syncDimension->add_child()->set_field(2 /* name field*/); - } - - *config.add_predicate() = scheduledJobPredicate; - *config.add_predicate() = isSyncingPredicate; - - auto metric = config.add_duration_metric(); - metric->set_bucket(FIVE_MINUTES); - metric->set_id(StringToId("scheduledJob")); - metric->set_what(scheduledJobPredicate.id()); - metric->set_condition(isSyncingPredicate.id()); - metric->set_aggregation_type(aggregationType); - auto dimensionWhat = metric->mutable_dimensions_in_what(); - dimensionWhat->set_field(android::util::SCHEDULED_JOB_STATE_CHANGED); - dimensionWhat->add_child()->set_field(2); // job name field. - *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions( - android::util::SYNC_STATE_CHANGED, {Position::FIRST}); - return config; -} - -} // namespace - -TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_SimpleCondition) { - for (bool isDimensionInConditionSubSetOfConditionTrackerDimension : {true, false}) { - for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) { - ConfigKey cfgKey; - auto config = CreateDurationMetricConfig_NoLink_SimpleCondition( - aggregationType, isDimensionInConditionSubSetOfConditionTrackerDimension); - int64_t bucketStartTimeNs = 10000000000; - int64_t bucketSizeNs = - TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; - - auto processor = CreateStatsLogProcessor( - bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); - EXPECT_EQ(processor->mMetricsManagers.size(), 1u); - EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - - std::vector<AttributionNodeInternal> attributions1 = { - CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; - - std::vector<AttributionNodeInternal> attributions2 = { - CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; - - std::vector<std::unique_ptr<LogEvent>> events; - - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(9999, "")}, "job0", bucketStartTimeNs + 1)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(9999, "")}, "job0",bucketStartTimeNs + 101)); - - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(9999, "")}, "job2", bucketStartTimeNs + 201)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(9999, "")}, "job2",bucketStartTimeNs + 500)); - - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(8888, "")}, "job2", bucketStartTimeNs + 600)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(8888, "")}, "job2",bucketStartTimeNs + bucketSizeNs + 850)); - - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(8888, "")}, "job1", bucketStartTimeNs + bucketSizeNs + 600)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(8888, "")}, "job1", bucketStartTimeNs + bucketSizeNs + 900)); - - events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 10)); - events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 50)); - - events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 200)); - events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", - bucketStartTimeNs + bucketSizeNs + 300)); - - events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", - bucketStartTimeNs + 400)); - events.push_back(CreateSyncEndEvent(attributions1, "ReadDoc", - bucketStartTimeNs + bucketSizeNs - 1)); - - events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", - bucketStartTimeNs + 401)); - events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", - bucketStartTimeNs + bucketSizeNs + 700)); - - sortLogEventsByTimestamp(&events); - - for (const auto& event : events) { - processor->OnLogEvent(event.get()); - } - - ConfigMetricsReportList reports; - vector<uint8_t> buffer; - processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, - true, ADB_DUMP, FAST, &buffer); - EXPECT_TRUE(buffer.size() > 0); - EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); - backfillDimensionPath(&reports); - backfillStringInReport(&reports); - backfillStartEndTimestamp(&reports); - - EXPECT_EQ(reports.reports_size(), 1); - EXPECT_EQ(reports.reports(0).metrics_size(), 1); - StatsLogReport::DurationMetricDataWrapper metrics; - sortMetricDataByDimensionsValue( - reports.reports(0).metrics(0).duration_metrics(), &metrics); - if (aggregationType == DurationMetric::SUM) { - EXPECT_EQ(metrics.data_size(), 4); - auto data = metrics.data(0); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job0"); // job name - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 111, "App1"); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 40); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - - data = metrics.data(1); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job1"); // job name - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 333, "App2"); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 100); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(2); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job2"); // job name - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 111, "App1"); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 201 + bucketSizeNs - 600); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 300); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(3); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job2"); // job name - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 333, "App2"); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 401 + bucketSizeNs - 600); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } else { - EXPECT_EQ(metrics.data_size(), 4); - auto data = metrics.data(0); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job0"); // job name - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 111, "App1"); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 40); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - - data = metrics.data(1); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job1"); // job name - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 333, "App2"); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 100); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(2); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job2"); // job name - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 111, "App1"); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 201); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 300); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(3); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job2"); // job name - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 333, "App2"); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 401 ); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 700); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } - } - } -} - -namespace { - -StatsdConfig createDurationMetric_Link_SimpleConditionConfig( - DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition) { - StatsdConfig config; - config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. - *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher(); - *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher(); - *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); - *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); - - auto scheduledJobPredicate = CreateScheduledJobPredicate(); - auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions(); - *dimensions = CreateAttributionUidDimensions( - android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); - dimensions->add_child()->set_field(2); // job name field. - - auto isSyncingPredicate = CreateIsSyncingPredicate(); - auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); - *syncDimension = CreateAttributionUidDimensions( - android::util::SYNC_STATE_CHANGED, {Position::FIRST}); - if (addExtraDimensionInCondition) { - syncDimension->add_child()->set_field(2 /* name field*/); - } - - *config.add_predicate() = scheduledJobPredicate; - *config.add_predicate() = isSyncingPredicate; - - auto metric = config.add_duration_metric(); - metric->set_bucket(FIVE_MINUTES); - metric->set_id(StringToId("scheduledJob")); - metric->set_what(scheduledJobPredicate.id()); - metric->set_condition(isSyncingPredicate.id()); - metric->set_aggregation_type(aggregationType); - *metric->mutable_dimensions_in_what() = CreateAttributionUidDimensions( - android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); - - auto links = metric->add_links(); - links->set_condition(isSyncingPredicate.id()); - *links->mutable_fields_in_what() = - CreateAttributionUidDimensions( - android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); - *links->mutable_fields_in_condition() = - CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST}); - return config; -} - -} // namespace - -TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_SimpleCondition) { - for (bool isFullLink : {true, false}) { - for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) { - ConfigKey cfgKey; - auto config = createDurationMetric_Link_SimpleConditionConfig( - aggregationType, !isFullLink); - int64_t bucketStartTimeNs = 10000000000; - int64_t bucketSizeNs = - TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; - - auto processor = CreateStatsLogProcessor( - bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); - EXPECT_EQ(processor->mMetricsManagers.size(), 1u); - EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - - std::vector<AttributionNodeInternal> attributions1 = { - CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; - - std::vector<AttributionNodeInternal> attributions2 = { - CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; - - std::vector<AttributionNodeInternal> attributions3 = { - CreateAttribution(444, "App3"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; - - std::vector<std::unique_ptr<LogEvent>> events; - - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(111, "App1")}, "job1", bucketStartTimeNs + 1)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(111, "App1")}, "job1",bucketStartTimeNs + 101)); - - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 201)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2",bucketStartTimeNs + 500)); - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 600)); - events.push_back( - CreateFinishScheduledJobEvent({CreateAttribution(333, "App2")}, "job2", - bucketStartTimeNs + bucketSizeNs + 850)); - - events.push_back( - CreateStartScheduledJobEvent({CreateAttribution(444, "App3")}, "job3", - bucketStartTimeNs + bucketSizeNs - 2)); - events.push_back( - CreateFinishScheduledJobEvent({CreateAttribution(444, "App3")}, "job3", - bucketStartTimeNs + bucketSizeNs + 900)); - - events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 50)); - events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 110)); - - events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", - bucketStartTimeNs + 300)); - events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", - bucketStartTimeNs + bucketSizeNs + 700)); - events.push_back(CreateSyncStartEvent(attributions2, "ReadDoc", - bucketStartTimeNs + 400)); - events.push_back(CreateSyncEndEvent(attributions2, "ReadDoc", - bucketStartTimeNs + bucketSizeNs - 1)); - - events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc", - bucketStartTimeNs + 550)); - events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc", - bucketStartTimeNs + 800)); - events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc", - bucketStartTimeNs + bucketSizeNs - 1)); - events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc", - bucketStartTimeNs + bucketSizeNs + 700)); - - sortLogEventsByTimestamp(&events); - - for (const auto& event : events) { - processor->OnLogEvent(event.get()); - } - - ConfigMetricsReportList reports; - vector<uint8_t> buffer; - processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, - true, ADB_DUMP, FAST, &buffer); - EXPECT_TRUE(buffer.size() > 0); - EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); - backfillDimensionPath(&reports); - backfillStringInReport(&reports); - backfillStartEndTimestamp(&reports); - - EXPECT_EQ(reports.reports_size(), 1); - EXPECT_EQ(reports.reports(0).metrics_size(), 1); - StatsLogReport::DurationMetricDataWrapper metrics; - sortMetricDataByDimensionsValue( - reports.reports(0).metrics(0).duration_metrics(), &metrics); - - if (aggregationType == DurationMetric::SUM) { - EXPECT_EQ(metrics.data_size(), 3); - auto data = metrics.data(0); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 50); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - - data = metrics.data(1); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 300 + bucketSizeNs - 600); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(2); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } else { - EXPECT_EQ(metrics.data_size(), 3); - auto data = metrics.data(0); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 50); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - - data = metrics.data(1); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 300); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 700); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(2); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 701); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } - } - } -} - -namespace { - -StatsdConfig createDurationMetric_PartialLink_SimpleConditionConfig( - DurationMetric::AggregationType aggregationType) { - StatsdConfig config; - config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. - *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher(); - *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher(); - *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); - *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); - - auto scheduledJobPredicate = CreateScheduledJobPredicate(); - auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions(); - *dimensions = CreateAttributionUidDimensions( - android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); - dimensions->add_child()->set_field(2); // job name field. - - auto isSyncingPredicate = CreateIsSyncingPredicate(); - auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); - *syncDimension = CreateAttributionUidDimensions( - android::util::SYNC_STATE_CHANGED, {Position::FIRST}); - syncDimension->add_child()->set_field(2 /* name field*/); - - *config.add_predicate() = scheduledJobPredicate; - *config.add_predicate() = isSyncingPredicate; - - auto metric = config.add_duration_metric(); - metric->set_bucket(FIVE_MINUTES); - metric->set_id(StringToId("scheduledJob")); - metric->set_what(scheduledJobPredicate.id()); - metric->set_condition(isSyncingPredicate.id()); - metric->set_aggregation_type(aggregationType); - *metric->mutable_dimensions_in_what() = CreateAttributionUidDimensions( - android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); - *metric->mutable_dimensions_in_condition() = *syncDimension; - - auto links = metric->add_links(); - links->set_condition(isSyncingPredicate.id()); - *links->mutable_fields_in_what() = - CreateAttributionUidDimensions( - android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); - *links->mutable_fields_in_condition() = - CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST}); - return config; -} - -} // namespace - -TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_SimpleCondition) { - for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) { - ConfigKey cfgKey; - auto config = createDurationMetric_PartialLink_SimpleConditionConfig( - aggregationType); - int64_t bucketStartTimeNs = 10000000000; - int64_t bucketSizeNs = - TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; - - auto processor = CreateStatsLogProcessor( - bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); - EXPECT_EQ(processor->mMetricsManagers.size(), 1u); - EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - - std::vector<AttributionNodeInternal> attributions1 = { - CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; - - std::vector<AttributionNodeInternal> attributions2 = { - CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; - - std::vector<AttributionNodeInternal> attributions3 = { - CreateAttribution(444, "App3"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; - - std::vector<std::unique_ptr<LogEvent>> events; - - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(111, "App1")}, "job1", bucketStartTimeNs + 1)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(111, "App1")}, "job1",bucketStartTimeNs + 101)); - - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 201)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2",bucketStartTimeNs + 500)); - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 600)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + bucketSizeNs + 850)); - - events.push_back( - CreateStartScheduledJobEvent({CreateAttribution(444, "App3")}, "job3", - bucketStartTimeNs + bucketSizeNs - 2)); - events.push_back( - CreateFinishScheduledJobEvent({CreateAttribution(444, "App3")}, "job3", - bucketStartTimeNs + bucketSizeNs + 900)); - - events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 50)); - events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 110)); - - events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", - bucketStartTimeNs + 300)); - events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", - bucketStartTimeNs + bucketSizeNs + 700)); - events.push_back(CreateSyncStartEvent(attributions2, "ReadDoc", - bucketStartTimeNs + 400)); - events.push_back(CreateSyncEndEvent(attributions2, "ReadDoc", - bucketStartTimeNs + bucketSizeNs - 1)); - - events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc", - bucketStartTimeNs + 550)); - events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc", - bucketStartTimeNs + 800)); - events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc", - bucketStartTimeNs + bucketSizeNs - 1)); - events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc", - bucketStartTimeNs + bucketSizeNs + 700)); - - sortLogEventsByTimestamp(&events); - - for (const auto& event : events) { - processor->OnLogEvent(event.get()); - } - - ConfigMetricsReportList reports; - vector<uint8_t> buffer; - processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true, - ADB_DUMP, FAST, &buffer); - EXPECT_TRUE(buffer.size() > 0); - EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); - backfillDimensionPath(&reports); - backfillStringInReport(&reports); - backfillStartEndTimestamp(&reports); - - EXPECT_EQ(reports.reports_size(), 1); - EXPECT_EQ(reports.reports(0).metrics_size(), 1); - StatsLogReport::DurationMetricDataWrapper metrics; - sortMetricDataByDimensionsValue( - reports.reports(0).metrics(0).duration_metrics(), &metrics); - - if (aggregationType == DurationMetric::SUM) { - EXPECT_EQ(4, metrics.data_size()); - auto data = metrics.data(0); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111); - EXPECT_EQ("ReadEmail", - data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 50); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - - data = metrics.data(1); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333); - EXPECT_EQ("ReadDoc", - data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 1 - 400 - 100); - - data = metrics.data(2); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333); - EXPECT_EQ("ReadEmail", - data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 300 + bucketSizeNs - 600); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(3); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 444); - EXPECT_EQ("ReadDoc", - data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } else { - EXPECT_EQ(metrics.data_size(), 4); - auto data = metrics.data(0); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111); - EXPECT_EQ("ReadEmail", - data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 50); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - - data = metrics.data(1); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333); - EXPECT_EQ("ReadDoc", - data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 100); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 1 - 600); - - data = metrics.data(2); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333); - EXPECT_EQ("ReadEmail", - data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 300); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 700); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - - data = metrics.data(3); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 444); - EXPECT_EQ("ReadDoc", - data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 701); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } - } -} - -#else -GTEST_LOG_(INFO) << "This test does nothing.\n"; -#endif - -} // namespace statsd -} // namespace os -} // namespace android diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp index 67c704eb87fd..839daa4b7f8a 100644 --- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp @@ -187,9 +187,9 @@ TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) { {getMockedDimensionKey(conditionTagId, 2, "222")}; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - EXPECT_CALL(*wizard, query(_, key1, _, _, _, _)).WillOnce(Return(ConditionState::kFalse)); + EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse)); - EXPECT_CALL(*wizard, query(_, key2, _, _, _, _)).WillOnce(Return(ConditionState::kTrue)); + EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue)); CountMetricProducer countProducer(kConfigKey, metric, 1 /*condition tracker index*/, wizard, bucketStartTimeNs, bucketStartTimeNs); diff --git a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp index d2fd95c818cf..f30873b92afc 100644 --- a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp @@ -113,9 +113,9 @@ TEST(EventMetricProducerTest, TestEventsWithSlicedCondition) { key2[StringToId("APP_IN_BACKGROUND_PER_UID")] = {getMockedDimensionKey(conditionTagId, 2, "222")}; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - EXPECT_CALL(*wizard, query(_, key1, _, _, _, _)).WillOnce(Return(ConditionState::kFalse)); + EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse)); - EXPECT_CALL(*wizard, query(_, key2, _, _, _, _)).WillOnce(Return(ConditionState::kTrue)); + EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue)); EventMetricProducer eventProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs); diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp index b9553a8fded8..47c21aa8f1df 100644 --- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp @@ -485,10 +485,6 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) { dim->set_field(tagId); dim->add_child()->set_field(1); - dim = metric.mutable_dimensions_in_condition(); - dim->set_field(conditionTag); - dim->add_child()->set_field(1); - UidMap uidMap; SimpleAtomMatcher atomMatcher; atomMatcher.set_atom_id(tagId); @@ -496,18 +492,14 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) { new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - EXPECT_CALL(*wizard, query(_, _, _, _, _, _)) + EXPECT_CALL(*wizard, query(_, _, _)) .WillRepeatedly( Invoke([](const int conditionIndex, const ConditionKey& conditionParameters, - const vector<Matcher>& dimensionFields, const bool isSubsetDim, - const bool isPartialLink, - std::unordered_set<HashableDimensionKey>* dimensionKeySet) { - dimensionKeySet->clear(); + const bool isPartialLink) { int pos[] = {1, 0, 0}; Field f(conditionTag, pos, 0); HashableDimensionKey key; key.mutableValues()->emplace_back(f, Value((int32_t)1000000)); - dimensionKeySet->insert(key); return ConditionState::kTrue; })); @@ -538,9 +530,6 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) { EXPECT_EQ(1UL, key.getDimensionKeyInWhat().getValues().size()); EXPECT_EQ(1000, key.getDimensionKeyInWhat().getValues()[0].mValue.int_value); - EXPECT_EQ(1UL, key.getDimensionKeyInCondition().getValues().size()); - EXPECT_EQ(1000000, key.getDimensionKeyInCondition().getValues()[0].mValue.int_value); - EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size()); vector<shared_ptr<LogEvent>> allData; diff --git a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp index bf047520cc77..100220b730d7 100644 --- a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp +++ b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp @@ -52,7 +52,6 @@ TEST(MaxDurationTrackerTest, TestSimpleMaxDuration) { const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1"); const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2"); - vector<Matcher> dimensionInCondition; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); @@ -63,7 +62,7 @@ TEST(MaxDurationTrackerTest, TestSimpleMaxDuration) { int64_t bucketNum = 0; int64_t metricId = 1; - MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition, + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {}); @@ -88,7 +87,6 @@ TEST(MaxDurationTrackerTest, TestStopAll) { const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1"); const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2"); - vector<Matcher> dimensionInCondition; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets; @@ -99,7 +97,7 @@ TEST(MaxDurationTrackerTest, TestStopAll) { int64_t bucketNum = 0; int64_t metricId = 1; - MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition, + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {}); @@ -124,7 +122,6 @@ TEST(MaxDurationTrackerTest, TestCrossBucketBoundary) { const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "1"); const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1"); const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2"); - vector<Matcher> dimensionInCondition; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets; @@ -135,7 +132,7 @@ TEST(MaxDurationTrackerTest, TestCrossBucketBoundary) { int64_t bucketNum = 0; int64_t metricId = 1; - MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition, + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {}); @@ -165,7 +162,6 @@ TEST(MaxDurationTrackerTest, TestCrossBucketBoundary_nested) { const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "1"); const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1"); const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2"); - vector<Matcher> dimensionInCondition; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets; @@ -176,7 +172,7 @@ TEST(MaxDurationTrackerTest, TestCrossBucketBoundary_nested) { int64_t bucketNum = 0; int64_t metricId = 1; - MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition, + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, true, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {}); @@ -202,7 +198,6 @@ TEST(MaxDurationTrackerTest, TestCrossBucketBoundary_nested) { TEST(MaxDurationTrackerTest, TestMaxDurationWithCondition) { const HashableDimensionKey conditionDimKey = key1; - vector<Matcher> dimensionInCondition; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); ConditionKey conditionKey1; @@ -223,7 +218,7 @@ TEST(MaxDurationTrackerTest, TestMaxDurationWithCondition) { int64_t eventStopTimeNs = conditionStops2 + 8 * NS_PER_SEC; int64_t metricId = 1; - MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false, bucketStartTimeNs, 0, bucketStartTimeNs, bucketSizeNs, true, false, {}); EXPECT_TRUE(tracker.mAnomalyTrackers.empty()); @@ -246,7 +241,6 @@ TEST(MaxDurationTrackerTest, TestMaxDurationWithCondition) { } TEST(MaxDurationTrackerTest, TestAnomalyDetection) { - vector<Matcher> dimensionInCondition; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); ConditionKey conditionKey1; @@ -273,7 +267,7 @@ TEST(MaxDurationTrackerTest, TestAnomalyDetection) { sp<AlarmMonitor> alarmMonitor; sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor); - MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, true, false, {anomalyTracker}); @@ -295,7 +289,6 @@ TEST(MaxDurationTrackerTest, TestAnomalyDetection) { // This tests that we correctly compute the predicted time of an anomaly assuming that the current // state continues forward as-is. TEST(MaxDurationTrackerTest, TestAnomalyPredictedTimestamp) { - vector<Matcher> dimensionInCondition; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); ConditionKey conditionKey1; @@ -333,7 +326,7 @@ TEST(MaxDurationTrackerTest, TestAnomalyPredictedTimestamp) { sp<AlarmMonitor> alarmMonitor; sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor); - MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, true, false, {anomalyTracker}); @@ -381,7 +374,6 @@ TEST(MaxDurationTrackerTest, TestAnomalyPredictedTimestamp) { // Suppose A starts, then B starts, and then A stops. We still need to set an anomaly based on the // elapsed duration of B. TEST(MaxDurationTrackerTest, TestAnomalyPredictedTimestamp_UpdatedOnStop) { - vector<Matcher> dimensionInCondition; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); ConditionKey conditionKey1; @@ -416,7 +408,7 @@ TEST(MaxDurationTrackerTest, TestAnomalyPredictedTimestamp_UpdatedOnStop) { sp<AlarmMonitor> alarmMonitor; sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor); - MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, true, false, {anomalyTracker}); @@ -434,4 +426,4 @@ TEST(MaxDurationTrackerTest, TestAnomalyPredictedTimestamp_UpdatedOnStop) { } // namespace android #else GTEST_LOG_(INFO) << "This test does nothing.\n"; -#endif
\ No newline at end of file +#endif diff --git a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp index 7c2b4236add8..1cd7bdbf7bb0 100644 --- a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp +++ b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp @@ -51,7 +51,6 @@ TEST(OringDurationTrackerTest, TestDurationOverlap) { const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); - vector<Matcher> dimensionInCondition; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets; @@ -62,7 +61,7 @@ TEST(OringDurationTrackerTest, TestDurationOverlap) { int64_t eventStartTimeNs = bucketStartTimeNs + 1; int64_t durationTimeNs = 2 * 1000; - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {}); @@ -84,7 +83,6 @@ TEST(OringDurationTrackerTest, TestDurationNested) { const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); - vector<Matcher> dimensionInCondition; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets; @@ -94,7 +92,7 @@ TEST(OringDurationTrackerTest, TestDurationNested) { int64_t bucketNum = 0; int64_t eventStartTimeNs = bucketStartTimeNs + 1; - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {}); @@ -117,7 +115,6 @@ TEST(OringDurationTrackerTest, TestStopAll) { {getMockedDimensionKey(TagId, 1, "maps")}; const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); - vector<Matcher> dimensionInCondition; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets; @@ -127,7 +124,7 @@ TEST(OringDurationTrackerTest, TestStopAll) { int64_t bucketNum = 0; int64_t eventStartTimeNs = bucketStartTimeNs + 1; - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {}); @@ -147,7 +144,6 @@ TEST(OringDurationTrackerTest, TestCrossBucketBoundary) { const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); - vector<Matcher> dimensionInCondition; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets; @@ -158,7 +154,7 @@ TEST(OringDurationTrackerTest, TestCrossBucketBoundary) { int64_t eventStartTimeNs = bucketStartTimeNs + 1; int64_t durationTimeNs = 2 * 1000; - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {}); @@ -186,13 +182,12 @@ TEST(OringDurationTrackerTest, TestDurationConditionChange) { const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); - vector<Matcher> dimensionInCondition; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); ConditionKey key1; key1[StringToId("APP_BACKGROUND")] = kConditionKey1; - EXPECT_CALL(*wizard, query(_, key1, _, _, _, _)) // #4 + EXPECT_CALL(*wizard, query(_, key1, _)) // #4 .WillOnce(Return(ConditionState::kFalse)); unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets; @@ -203,7 +198,7 @@ TEST(OringDurationTrackerTest, TestDurationConditionChange) { int64_t eventStartTimeNs = bucketStartTimeNs + 1; int64_t durationTimeNs = 2 * 1000; - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, true, false, {}); @@ -224,13 +219,12 @@ TEST(OringDurationTrackerTest, TestDurationConditionChange2) { const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); - vector<Matcher> dimensionInCondition; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); ConditionKey key1; key1[StringToId("APP_BACKGROUND")] = kConditionKey1; - EXPECT_CALL(*wizard, query(_, key1, _, _, _, _)) + EXPECT_CALL(*wizard, query(_, key1, _)) .Times(2) .WillOnce(Return(ConditionState::kFalse)) .WillOnce(Return(ConditionState::kTrue)); @@ -243,7 +237,7 @@ TEST(OringDurationTrackerTest, TestDurationConditionChange2) { int64_t eventStartTimeNs = bucketStartTimeNs + 1; int64_t durationTimeNs = 2 * 1000; - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, true, false, {}); @@ -266,13 +260,12 @@ TEST(OringDurationTrackerTest, TestDurationConditionChangeNested) { const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); - vector<Matcher> dimensionInCondition; sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); ConditionKey key1; key1[StringToId("APP_BACKGROUND")] = kConditionKey1; - EXPECT_CALL(*wizard, query(_, key1, _, _, _, _)) // #4 + EXPECT_CALL(*wizard, query(_, key1, _)) // #4 .WillOnce(Return(ConditionState::kFalse)); unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets; @@ -282,7 +275,7 @@ TEST(OringDurationTrackerTest, TestDurationConditionChangeNested) { int64_t bucketNum = 0; int64_t eventStartTimeNs = bucketStartTimeNs + 1; - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, true, false, {}); @@ -306,7 +299,6 @@ TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp) { const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); - vector<Matcher> dimensionInCondition; Alert alert; alert.set_id(101); alert.set_metric_id(1); @@ -324,7 +316,7 @@ TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp) { sp<AlarmMonitor> alarmMonitor; sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor); - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, true, false, {anomalyTracker}); @@ -371,7 +363,6 @@ TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp) { } TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp2) { - vector<Matcher> dimensionInCondition; Alert alert; alert.set_id(101); alert.set_metric_id(1); @@ -387,7 +378,7 @@ TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp2) { sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor); OringDurationTracker tracker(kConfigKey, metricId, DEFAULT_METRIC_DIMENSION_KEY, wizard, 1, - dimensionInCondition, + true, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, true, false, {anomalyTracker}); @@ -415,7 +406,7 @@ TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp3) { for (int j = 0; j < 3; j++) { int64_t thresholdNs = j * bucketSizeNs + 5 * NS_PER_SEC; for (int i = 0; i <= 7; ++i) { - vector<Matcher> dimensionInCondition; + Alert alert; alert.set_id(101); alert.set_metric_id(1); @@ -432,7 +423,7 @@ TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp3) { sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor); OringDurationTracker tracker(kConfigKey, metricId, DEFAULT_METRIC_DIMENSION_KEY, - wizard, 1, dimensionInCondition, + wizard, 1, true, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, true, false, {anomalyTracker}); @@ -472,7 +463,6 @@ TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm) { const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); - vector<Matcher> dimensionInCondition; Alert alert; alert.set_id(101); alert.set_metric_id(1); @@ -491,7 +481,7 @@ TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm) { sp<AlarmMonitor> alarmMonitor; sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor); - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true /*nesting*/, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {anomalyTracker}); @@ -522,7 +512,6 @@ TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm) { const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); - vector<Matcher> dimensionInCondition; Alert alert; alert.set_id(101); alert.set_metric_id(1); @@ -541,7 +530,7 @@ TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm) { sp<AlarmMonitor> alarmMonitor; sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor); - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true /*nesting*/, bucketStartTimeNs, 0, bucketStartTimeNs, bucketSizeNs, false, false, {anomalyTracker}); @@ -589,4 +578,4 @@ TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm) { } // namespace android #else GTEST_LOG_(INFO) << "This test does nothing.\n"; -#endif
\ No newline at end of file +#endif diff --git a/cmds/statsd/tests/metrics/metrics_test_helper.h b/cmds/statsd/tests/metrics/metrics_test_helper.h index 97c107228f9c..329e39fc4eff 100644 --- a/cmds/statsd/tests/metrics/metrics_test_helper.h +++ b/cmds/statsd/tests/metrics/metrics_test_helper.h @@ -26,11 +26,9 @@ namespace statsd { class MockConditionWizard : public ConditionWizard { public: - MOCK_METHOD6(query, + MOCK_METHOD3(query, ConditionState(const int conditionIndex, const ConditionKey& conditionParameters, - const vector<Matcher>& dimensionFields, - const bool isSubsetDim, const bool isPartialLink, - std::unordered_set<HashableDimensionKey>* dimensionKeySet)); + const bool isPartialLink)); }; class MockStatsPullerManager : public StatsPullerManager { @@ -55,4 +53,4 @@ void buildSimpleAtomFieldMatcher(const int tagId, FieldMatcher* matcher); } // namespace statsd } // namespace os -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java index fcdc81cf7533..d03bea2fb19e 100644 --- a/core/java/android/content/pm/UserInfo.java +++ b/core/java/android/content/pm/UserInfo.java @@ -328,6 +328,14 @@ public class UserInfo implements Parcelable { } /** @hide */ + public String toFullString() { + return "UserInfo[id=" + id + + ", name=" + name + + ", flags=" + flagsToString(flags) + + "]"; + } + + /** @hide */ public static String flagsToString(int flags) { return DebugUtils.flagsToString(UserInfo.class, "FLAG_", flags); } diff --git a/core/java/android/service/textclassifier/TextClassifierService.java b/core/java/android/service/textclassifier/TextClassifierService.java index 9108c3365f77..5143f1820c2d 100644 --- a/core/java/android/service/textclassifier/TextClassifierService.java +++ b/core/java/android/service/textclassifier/TextClassifierService.java @@ -51,7 +51,6 @@ import android.view.textclassifier.TextSelection; import com.android.internal.util.Preconditions; -import java.lang.ref.WeakReference; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -431,23 +430,18 @@ public abstract class TextClassifierService extends Service { * Forwards the callback result to a wrapped binder callback. */ private static final class ProxyCallback<T extends Parcelable> implements Callback<T> { - private WeakReference<ITextClassifierCallback> mTextClassifierCallback; + private ITextClassifierCallback mTextClassifierCallback; private ProxyCallback(ITextClassifierCallback textClassifierCallback) { - mTextClassifierCallback = - new WeakReference<>(Preconditions.checkNotNull(textClassifierCallback)); + mTextClassifierCallback = Preconditions.checkNotNull(textClassifierCallback); } @Override public void onSuccess(T result) { - ITextClassifierCallback callback = mTextClassifierCallback.get(); - if (callback == null) { - return; - } try { Bundle bundle = new Bundle(1); bundle.putParcelable(KEY_RESULT, result); - callback.onSuccess(bundle); + mTextClassifierCallback.onSuccess(bundle); } catch (RemoteException e) { Slog.d(LOG_TAG, "Error calling callback"); } @@ -455,13 +449,9 @@ public abstract class TextClassifierService extends Service { @Override public void onFailure(CharSequence error) { - ITextClassifierCallback callback = mTextClassifierCallback.get(); - if (callback == null) { - return; - } try { Slog.w(LOG_TAG, "Request fail: " + error); - callback.onFailure(); + mTextClassifierCallback.onFailure(); } catch (RemoteException e) { Slog.d(LOG_TAG, "Error calling callback"); } diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java index 51ca80524090..d0f80936f477 100644 --- a/core/java/android/widget/SelectionActionModeHelper.java +++ b/core/java/android/widget/SelectionActionModeHelper.java @@ -999,6 +999,7 @@ public final class SelectionActionModeHelper { } private void onTimeOut() { + Log.d(LOG_TAG, "Timeout in TextClassificationAsyncTask"); if (getStatus() == Status.RUNNING) { onPostExecute(mTimeOutResultSupplier.get()); } diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 2067735f2620..96c0cf3fd86a 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2927,7 +2927,6 @@ <public type="attr" name="enforceStatusBarContrast" id="0x01010604" /> <public type="attr" name="enforceNavigationBarContrast" id="0x01010605" /> <public type="attr" name="identifier" id="0x01010606" /> - <public type="attr" name="forceQueryable" id="0x01010608" /> <!-- @hide @SystemApi --> <public type="drawable" name="ic_info" id="0x010800b4" /> @@ -3000,6 +2999,7 @@ <public-group type="attr" first-id="0x01010607"> <public name="importantForContentCapture" /> + <public name="forceQueryable" /> </public-group> <public-group type="drawable" first-id="0x010800b5"> diff --git a/location/lib/Android.bp b/location/lib/Android.bp index db63889d7743..b15cc5ccd656 100644 --- a/location/lib/Android.bp +++ b/location/lib/Android.bp @@ -24,6 +24,5 @@ java_sdk_library { srcs_lib: "framework-minus-apex", // TODO(b/70046217): remove core/java and android below. It was added to provide definitions for // types like android.os.Bundle - srcs_lib_whitelist_dirs: ["core/java", "location/java"], srcs_lib_whitelist_pkgs: ["android", "com.android.internal.location"], } diff --git a/media/java/android/media/IMediaRoute2ProviderClient.aidl b/media/java/android/media/IMediaRoute2ProviderClient.aidl index 8d08beb4a72c..6f44d45c0a12 100644 --- a/media/java/android/media/IMediaRoute2ProviderClient.aidl +++ b/media/java/android/media/IMediaRoute2ProviderClient.aidl @@ -22,5 +22,5 @@ import android.media.MediaRoute2ProviderInfo; * @hide */ oneway interface IMediaRoute2ProviderClient { - void notifyProviderInfoUpdated(in MediaRoute2ProviderInfo info); + void updateProviderInfo(in MediaRoute2ProviderInfo info); } diff --git a/media/java/android/media/IMediaRouter2Client.aidl b/media/java/android/media/IMediaRouter2Client.aidl index 774d6a764f32..26184af699db 100644 --- a/media/java/android/media/IMediaRouter2Client.aidl +++ b/media/java/android/media/IMediaRouter2Client.aidl @@ -16,10 +16,12 @@ package android.media; +import android.media.MediaRoute2ProviderInfo; + /** * @hide */ oneway interface IMediaRouter2Client { - void notifyStateChanged(); void notifyRestoreRoute(); + void notifyProviderInfosUpdated(in List<MediaRoute2ProviderInfo> providers); } diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl index 08266a5a2051..1b713b6ab74b 100644 --- a/media/java/android/media/IMediaRouterService.aidl +++ b/media/java/android/media/IMediaRouterService.aidl @@ -42,7 +42,7 @@ interface IMediaRouterService { void requestUpdateVolume(IMediaRouterClient client, String routeId, int direction); // Methods for media router 2 - void registerClient2AsUser(IMediaRouter2Client client, String packageName, int userId); + void registerClient2(IMediaRouter2Client client, String packageName); void unregisterClient2(IMediaRouter2Client client); void sendControlRequest(IMediaRouter2Client client, in MediaRoute2Info route, in Intent request); /** @@ -54,8 +54,7 @@ interface IMediaRouterService { void selectRoute2(IMediaRouter2Client client, in @nullable MediaRoute2Info route); void setControlCategories(IMediaRouter2Client client, in List<String> categories); - void registerManagerAsUser(IMediaRouter2Manager manager, - String packageName, int userId); + void registerManager(IMediaRouter2Manager manager, String packageName); void unregisterManager(IMediaRouter2Manager manager); /** * Changes the selected route of an application. diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java index b89b0b1a5f02..e8e0f826e6b6 100644 --- a/media/java/android/media/MediaRoute2ProviderService.java +++ b/media/java/android/media/MediaRoute2ProviderService.java @@ -98,7 +98,7 @@ public abstract class MediaRoute2ProviderService extends Service { return; } try { - mClient.notifyProviderInfoUpdated(mProviderInfo); + mClient.updateProviderInfo(mProviderInfo); } catch (RemoteException ex) { Log.w(TAG, "Failed to send onProviderInfoUpdated"); } diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java index f4dffa28f133..8e29e34caa14 100644 --- a/media/java/android/media/MediaRouter2.java +++ b/media/java/android/media/MediaRouter2.java @@ -16,13 +16,16 @@ package android.media; +import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; + import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.content.Context; import android.content.Intent; +import android.os.Handler; +import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.UserHandle; import android.util.Log; import com.android.internal.annotations.GuardedBy; @@ -58,6 +61,12 @@ public class MediaRouter2 { private Client mClient; private final String mPackageName; + final Handler mHandler; + + List<MediaRoute2ProviderInfo> mProviders = Collections.emptyList(); + volatile List<MediaRoute2Info> mRoutes = Collections.emptyList(); + + MediaRoute2Info mSelectedRoute; /** * Gets an instance of the media router associated with the context. @@ -78,6 +87,7 @@ public class MediaRouter2 { ServiceManager.getService(Context.MEDIA_ROUTER_SERVICE)); mPackageName = mContext.getPackageName(); //TODO: read control categories from the manifest + mHandler = new Handler(Looper.getMainLooper()); } /** @@ -100,25 +110,10 @@ public class MediaRouter2 { Objects.requireNonNull(executor, "executor must not be null"); Objects.requireNonNull(callback, "callback must not be null"); + CallbackRecord record; // This is required to prevent adding the same callback twice. synchronized (mCallbackRecords) { - if (mCallbackRecords.size() == 0) { - synchronized (sLock) { - Client client = new Client(); - try { - mMediaRouterService.registerClient2AsUser(client, mPackageName, - UserHandle.myUserId()); - //TODO: We should merge control categories of callbacks. - mMediaRouterService.setControlCategories(client, mControlCategories); - mClient = client; - } catch (RemoteException ex) { - Log.e(TAG, "Unable to register media router.", ex); - } - } - } - final int index = findCallbackRecordIndexLocked(callback); - CallbackRecord record; if (index < 0) { record = new CallbackRecord(callback); mCallbackRecords.add(record); @@ -129,6 +124,20 @@ public class MediaRouter2 { record.mFlags = flags; } + synchronized (sLock) { + if (mClient == null) { + Client client = new Client(); + try { + mMediaRouterService.registerClient2(client, mPackageName); + mMediaRouterService.setControlCategories(client, mControlCategories); + mClient = client; + } catch (RemoteException ex) { + Log.e(TAG, "Unable to register media router.", ex); + } + } + } + record.notifyRoutes(); + //TODO: Update discovery request here. } @@ -172,10 +181,9 @@ public class MediaRouter2 { Objects.requireNonNull(controlCategories, "control categories must not be null"); Client client; - List<String> newControlCategories; + List<String> newControlCategories = new ArrayList<>(controlCategories); synchronized (sLock) { - mControlCategories = new ArrayList<>(controlCategories); - newControlCategories = mControlCategories; + mControlCategories = newControlCategories; client = mClient; } if (client != null) { @@ -185,8 +193,29 @@ public class MediaRouter2 { Log.e(TAG, "Unable to set control categories.", ex); } } + mHandler.sendMessage(obtainMessage(MediaRouter2::refreshAndNotifyRoutes, this)); } + /** + * Gets the list of {@link MediaRoute2Info routes} currently known to the media router. + * + * @return the list of routes that support at least one of the control categories set by + * the application + */ + @NonNull + public List<MediaRoute2Info> getRoutes() { + return mRoutes; + } + + /** + * Gets the currently selected route. + * + * @return the selected route + */ + @NonNull + public MediaRoute2Info getSelectedRoute() { + return mSelectedRoute; + } /** * Selects the specified route. @@ -199,6 +228,7 @@ public class MediaRouter2 { Client client; synchronized (sLock) { + mSelectedRoute = route; client = mClient; } if (client != null) { @@ -247,6 +277,61 @@ public class MediaRouter2 { return -1; } + void onProviderInfosUpdated(List<MediaRoute2ProviderInfo> providers) { + if (providers == null) { + Log.w(TAG, "Providers info is null."); + return; + } + + mProviders = providers; + refreshAndNotifyRoutes(); + } + + void refreshAndNotifyRoutes() { + ArrayList<MediaRoute2Info> routes = new ArrayList<>(); + + List<String> controlCategories; + synchronized (sLock) { + controlCategories = mControlCategories; + } + + for (MediaRoute2ProviderInfo provider : mProviders) { + updateProvider(provider, controlCategories, routes); + } + + //TODO: Can orders be changed? + if (!Objects.equals(mRoutes, routes)) { + mRoutes = Collections.unmodifiableList(routes); + notifyRouteListChanged(mRoutes); + } + } + + void updateProvider(MediaRoute2ProviderInfo provider, List<String> controlCategories, + List<MediaRoute2Info> outRoutes) { + if (provider == null || !provider.isValid()) { + Log.w(TAG, "Ignoring invalid provider : " + provider); + } + + final Collection<MediaRoute2Info> routes = provider.getRoutes(); + for (MediaRoute2Info route : routes) { + if (!route.isValid()) { + Log.w(TAG, "Ignoring invalid route : " + route); + continue; + } + if (!route.supportsControlCategory(controlCategories)) { + continue; + } + outRoutes.add(route); + } + } + + void notifyRouteListChanged(List<MediaRoute2Info> routes) { + for (CallbackRecord record: mCallbackRecords) { + record.mExecutor.execute( + () -> record.mCallback.onRoutesChanged(routes)); + } + } + /** * Interface for receiving events about media routing changes. */ @@ -265,9 +350,14 @@ public class MediaRouter2 { * Called when a route is removed. */ public void onRouteRemoved(MediaRoute2Info routeInfo) {} + + /** + * Called when the list of routes is changed. + */ + public void onRoutesChanged(@NonNull List<MediaRoute2Info> routes) {} } - static final class CallbackRecord { + final class CallbackRecord { public final Callback mCallback; public Executor mExecutor; public int mFlags; @@ -275,13 +365,25 @@ public class MediaRouter2 { CallbackRecord(@NonNull Callback callback) { mCallback = callback; } + + void notifyRoutes() { + final List<MediaRoute2Info> routes = mRoutes; + // notify only when bound to media router service. + //TODO: Correct the condition when control category, default rotue, .. are finalized. + if (routes.size() > 0) { + mExecutor.execute(() -> mCallback.onRoutesChanged(routes)); + } + } } class Client extends IMediaRouter2Client.Stub { @Override - public void notifyStateChanged() throws RemoteException {} + public void notifyRestoreRoute() throws RemoteException {} @Override - public void notifyRestoreRoute() throws RemoteException {} + public void notifyProviderInfosUpdated(List<MediaRoute2ProviderInfo> info) { + mHandler.sendMessage(obtainMessage(MediaRouter2::onProviderInfosUpdated, + MediaRouter2.this, info)); + } } } diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java index 6c53f7d6d73f..0b645691ea3b 100644 --- a/media/java/android/media/MediaRouter2Manager.java +++ b/media/java/android/media/MediaRouter2Manager.java @@ -25,7 +25,6 @@ import android.content.Context; import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; @@ -104,26 +103,28 @@ public class MediaRouter2Manager { Objects.requireNonNull(executor, "executor must not be null"); Objects.requireNonNull(callback, "callback must not be null"); + CallbackRecord callbackRecord; synchronized (mCallbacks) { if (findCallbackRecordIndexLocked(callback) >= 0) { Log.w(TAG, "Ignoring to add the same callback twice."); return; } - synchronized (sLock) { - if (mCallbacks.size() == 0) { - Client client = new Client(); - try { - mMediaRouterService.registerManagerAsUser(client, mPackageName, - UserHandle.myUserId()); - mClient = client; - } catch (RemoteException ex) { - Log.e(TAG, "Unable to register media router manager.", ex); - } + callbackRecord = new CallbackRecord(executor, callback); + mCallbacks.add(callbackRecord); + } + + synchronized (sLock) { + if (mClient == null) { + Client client = new Client(); + try { + mMediaRouterService.registerManager(client, mPackageName); + mClient = client; + } catch (RemoteException ex) { + Log.e(TAG, "Unable to register media router manager.", ex); } + } else { + callbackRecord.notifyRoutes(); } - CallbackRecord record = new CallbackRecord(executor, callback); - mCallbacks.add(record); - record.notifyRoutes(); } } @@ -149,6 +150,7 @@ public class MediaRouter2Manager { } catch (RemoteException ex) { Log.e(TAG, "Unable to unregister media router manager", ex); } + mClient.notifyProviderInfosUpdated(Collections.emptyList()); mClient = null; } } @@ -255,6 +257,10 @@ public class MediaRouter2Manager { final MediaRoute2ProviderInfo prevProvider = mProviders.get(index); final Set<String> updatedRouteIds = new HashSet<>(); for (MediaRoute2Info routeInfo : routes) { + if (!routeInfo.isValid()) { + Log.w(TAG, "Ignoring invalid route : " + routeInfo); + continue; + } final MediaRoute2Info prevRoute = prevProvider.getRoute(routeInfo.getId()); if (prevRoute == null) { notifyRouteAdded(routeInfo); @@ -303,7 +309,7 @@ public class MediaRouter2Manager { void notifyRouteListChanged() { for (CallbackRecord record: mCallbacks) { record.mExecutor.execute( - () -> record.mCallback.onRouteListChanged(mRoutes)); + () -> record.mCallback.onRoutesChanged(mRoutes)); } } @@ -369,10 +375,10 @@ public class MediaRouter2Manager { public void onRouteSelected(@NonNull String packageName, @Nullable MediaRoute2Info route) {} /** - * Called when the list of routes are changed. + * Called when the list of routes is changed. * A client may refresh available routes for each application. */ - public void onRouteListChanged(@NonNull List<MediaRoute2Info> routes) {} + public void onRoutesChanged(@NonNull List<MediaRoute2Info> routes) {} } final class CallbackRecord { @@ -385,6 +391,7 @@ public class MediaRouter2Manager { } void notifyRoutes() { + mExecutor.execute(() -> mCallback.onRoutesChanged(mRoutes)); for (MediaRoute2Info routeInfo : mRoutes) { mExecutor.execute( () -> mCallback.onRouteAdded(routeInfo)); diff --git a/media/lib/signer/Android.bp b/media/lib/signer/Android.bp index f320397bc84b..338ec12a9e28 100644 --- a/media/lib/signer/Android.bp +++ b/media/lib/signer/Android.bp @@ -19,6 +19,5 @@ java_sdk_library { srcs: ["java/**/*.java"], api_packages: ["com.android.mediadrm.signer"], srcs_lib: "framework-minus-apex", - srcs_lib_whitelist_dirs: ["media/java"], srcs_lib_whitelist_pkgs: ["android.media"], } diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java index 946fb5e0e0ec..3abf0a4941e6 100644 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java +++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java @@ -18,6 +18,7 @@ package com.android.mediaroutertest; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.timeout; @@ -42,10 +43,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; @RunWith(AndroidJUnit4.class) @SmallTest @@ -96,6 +95,7 @@ public class MediaRouterManagerTest { mPackageName = mContext.getPackageName(); } + //TODO: Move to a seperate file @Test public void testMediaRoute2Info() { MediaRoute2Info routeInfo1 = new MediaRoute2Info.Builder("id", "name") @@ -159,7 +159,7 @@ public class MediaRouterManagerTest { mRouter.unregisterCallback(mockRouterCallback); verify(mockCallback, timeout(TIMEOUT_MS)) - .onRouteListChanged(argThat(routes -> routes.size() > 0)); + .onRoutesChanged(argThat(routes -> routes.size() > 0)); Map<String, MediaRoute2Info> routes = createRouteMap(mManager.getAvailableRoutes(mPackageName)); @@ -170,40 +170,48 @@ public class MediaRouterManagerTest { mManager.unregisterCallback(mockCallback); } + /** + * Tests if we get proper routes for application that has special control category. + */ @Test - public void onRouteSelectedTest() throws Exception { - CountDownLatch latch = new CountDownLatch(1); + public void testGetRoutes() throws Exception { + MediaRouter2.Callback mockCallback = mock(MediaRouter2.Callback.class); + mRouter.setControlCategories(CONTROL_CATEGORIES_SPECIAL); + mRouter.registerCallback(mExecutor, mockCallback); + verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce()) + .onRoutesChanged(argThat(routes -> routes.size() > 0)); + Map<String, MediaRoute2Info> routes = createRouteMap(mRouter.getRoutes()); + Assert.assertEquals(1, routes.size()); + Assert.assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY)); + + mRouter.unregisterCallback(mockCallback); + } + + @Test + public void testOnRouteSelected() throws Exception { MediaRouter2.Callback mockRouterCallback = mock(MediaRouter2.Callback.class); + MediaRouter2Manager.Callback managerCallback = mock(MediaRouter2Manager.Callback.class); + + mManager.registerCallback(mExecutor, managerCallback); + mRouter.setControlCategories(CONTROL_CATEGORIES_ALL); mRouter.registerCallback(mExecutor, mockRouterCallback); - MediaRouter2Manager.Callback managerCallback = new MediaRouter2Manager.Callback() { - MediaRoute2Info mSelectedRoute = null; - - @Override - public void onRouteAdded(MediaRoute2Info routeInfo) { - if (mSelectedRoute == null) { - mSelectedRoute = routeInfo; - mManager.selectRoute(mPackageName, mSelectedRoute); - } - } - - @Override - public void onRouteSelected(String packageName, MediaRoute2Info route) { - if (TextUtils.equals(packageName, mPackageName) - && mSelectedRoute != null - && route != null - && TextUtils.equals(route.getId(), mSelectedRoute.getId())) { - latch.countDown(); - } - } - }; + verify(managerCallback, timeout(TIMEOUT_MS)) + .onRoutesChanged(argThat(routes -> routes.size() > 0)); - mManager.registerCallback(mExecutor, managerCallback); + Map<String, MediaRoute2Info> routes = + createRouteMap(mManager.getAvailableRoutes(mPackageName)); - Assert.assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + MediaRoute2Info routeToSelect = routes.get(ROUTE_ID1); + mManager.selectRoute(mPackageName, routeToSelect); + + assertNotNull(routeToSelect); + verify(managerCallback, timeout(TIMEOUT_MS)) + .onRouteAdded(argThat(route -> route.equals(routeToSelect))); mManager.unregisterCallback(managerCallback); + mRouter.unregisterCallback(mockRouterCallback); } /** @@ -219,7 +227,7 @@ public class MediaRouterManagerTest { mRouter.registerCallback(mExecutor, routerCallback); verify(managerCallback, timeout(TIMEOUT_MS)) - .onRouteListChanged(argThat(routes -> routes.size() > 0)); + .onRoutesChanged(argThat(routes -> routes.size() > 0)); Map<String, MediaRoute2Info> routes = createRouteMap(mManager.getAvailableRoutes(mPackageName)); @@ -244,7 +252,8 @@ public class MediaRouterManagerTest { mManager.unregisterCallback(managerCallback); } - Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) { + // Helper for getting routes easily + static Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) { Map<String, MediaRoute2Info> routeMap = new HashMap<>(); for (MediaRoute2Info route : routes) { routeMap.put(route.getId(), route); diff --git a/packages/SettingsLib/SearchWidget/res/values-pt-rPT/strings.xml b/packages/SettingsLib/SearchWidget/res/values-pt-rPT/strings.xml index 7846be161c0f..363d88544a03 100644 --- a/packages/SettingsLib/SearchWidget/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/SearchWidget/res/values-pt-rPT/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="search_menu" msgid="1604061903696928905">"Definições de pesquisa"</string> + <string name="search_menu" msgid="1604061903696928905">"Pesquisar definições"</string> </resources> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index 13890e029274..f1fc9f9e3d4e 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -452,7 +452,7 @@ <string name="cancel" msgid="6859253417269739139">"বাতিল"</string> <string name="okay" msgid="1997666393121016642">"ঠিক আছে"</string> <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"চালু করুন"</string> - <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"\'বিরক্ত করবেন না\' মোড চালু করুন"</string> + <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"\'বিরক্ত করবে না\' মোড চালু করুন"</string> <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"কখনও নয়"</string> <string name="zen_interruption_level_priority" msgid="2078370238113347720">"শুধুমাত্র অগ্রাধিকার"</string> <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index 2734f4e28632..7874aeb02996 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -286,7 +286,7 @@ <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Esperar que se conecte el depurador para iniciar la aplicación"</string> <string name="debug_input_category" msgid="1811069939601180246">"Entrada"</string> <string name="debug_drawing_category" msgid="6755716469267367852">"Dibujo"</string> - <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Representación acelerada mediante hardware"</string> + <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Procesamiento acelerado mediante hardware"</string> <string name="media_category" msgid="4388305075496848353">"Multimedia"</string> <string name="debug_monitoring_category" msgid="7640508148375798343">"Supervisión"</string> <string name="strict_mode" msgid="1938795874357830695">"Modo estricto"</string> diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml index 5cffafed6689..7368f1d105f2 100644 --- a/packages/SettingsLib/res/values-hy/arrays.xml +++ b/packages/SettingsLib/res/values-hy/arrays.xml @@ -43,7 +43,7 @@ <item msgid="8937994881315223448">"Միացված է <xliff:g id="NETWORK_NAME">%1$s</xliff:g>-ին"</item> <item msgid="1330262655415760617">"Անջատված"</item> <item msgid="7698638434317271902">"Անջատվում է <xliff:g id="NETWORK_NAME">%1$s</xliff:g>-ից…"</item> - <item msgid="197508606402264311">"Անջատած է"</item> + <item msgid="197508606402264311">"Անջատված է"</item> <item msgid="8578370891960825148">"Անհաջող"</item> <item msgid="5660739516542454527">"Արգելափակված"</item> <item msgid="1805837518286731242">"Վատ ցանցից ժամանակավոր խուսափում"</item> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index bf587405c668..a74b4ae3ae9e 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -263,7 +263,7 @@ <string name="debug_view_attributes" msgid="6485448367803310384">"Միացնել ցուցադրման հատկանիշների ստուգումը"</string> <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Միշտ ակտիվացրած պահել բջջային տվյալները, նույնիսկ Wi‑Fi-ը միացրած ժամանակ (ցանցերի միջև արագ փոխարկման համար):"</string> <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Օգտագործել սարքակազմի արագացման միացումը, եթե հասանելի է"</string> - <string name="adb_warning_title" msgid="6234463310896563253">"Թույլատրե՞լ USB-ի վրիպազերծումը:"</string> + <string name="adb_warning_title" msgid="6234463310896563253">"Թույլատրե՞լ USB վրիպազերծումը:"</string> <string name="adb_warning_message" msgid="7316799925425402244">"USB վրիպազերծումը միայն ծրագրավորման նպատակների համար է: Օգտագործեք այն ձեր համակարգչից տվյալները ձեր սարք պատճենելու համար, առանց ծանուցման ձեր սարքի վրա ծրագրեր տեղադրելու և տվյալների մատյանը ընթերցելու համար:"</string> <string name="adb_keys_warning_message" msgid="5659849457135841625">"Փակե՞լ USB-ի վրիպազերծման մուտքը` անջատելով այն բոլոր համակարգիչներից, որտեղ նախկինում թույլատրել էիք:"</string> <string name="dev_settings_warning_title" msgid="7244607768088540165">"Ընդունե՞լ ծրագրավորման կարգավորումներ:"</string> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index cf442b73e721..57e690d46b23 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -159,7 +159,7 @@ <string name="tts_default_pitch_title" msgid="6135942113172488671">"ஒலித்திறன்"</string> <string name="tts_default_pitch_summary" msgid="1944885882882650009">"உருவாக்கப்படும் பேச்சின் டோன் பாதிக்கப்படும்"</string> <string name="tts_default_lang_title" msgid="8018087612299820556">"மொழி"</string> - <string name="tts_lang_use_system" msgid="2679252467416513208">"அமைப்பின் மொழியில்"</string> + <string name="tts_lang_use_system" msgid="2679252467416513208">"அமைப்பின் மொழியைப் பயன்படுத்தவும்"</string> <string name="tts_lang_not_selected" msgid="7395787019276734765">"மொழி தேர்ந்தெடுக்கப்படவில்லை"</string> <string name="tts_default_lang_summary" msgid="5219362163902707785">"பேசப்படும் உரைக்கு மொழி சார்ந்த குரலை அமைக்கிறது"</string> <string name="tts_play_example_title" msgid="7094780383253097230">"எடுத்துக்காட்டைக் கவனிக்கவும்"</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 83636dc19beb..eb6160a47fce 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -143,7 +143,7 @@ <string name="data_usage_ota" msgid="5377889154805560860">"సిస్టమ్ అప్డేట్లు"</string> <string name="tether_settings_title_usb" msgid="6688416425801386511">"USB టీథరింగ్"</string> <string name="tether_settings_title_wifi" msgid="3277144155960302049">"పోర్టబుల్ హాట్స్పాట్"</string> - <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"బ్లూటూత్ టీథరింగ్"</string> + <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"బ్లూటూత్ టెథెరింగ్"</string> <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"టీథరింగ్"</string> <string name="tether_settings_title_all" msgid="8356136101061143841">"టీథరింగ్ & పోర్టబుల్ హాట్స్పాట్"</string> <string name="managed_user_title" msgid="8109605045406748842">"అన్ని కార్యాలయ అనువర్తనాలు"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 4e2d6fa76ad0..5c06c80a049c 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -201,7 +201,7 @@ <string name="vpn_settings_not_available" msgid="956841430176985598">"Cài đặt VPN không khả dụng cho người dùng này"</string> <string name="tethering_settings_not_available" msgid="6765770438438291012">"Cài đặt chia sẻ kết nối không khả dụng cho người dùng này"</string> <string name="apn_settings_not_available" msgid="7873729032165324000">"Cài đặt tên điểm truy cập không khả dụng cho người dùng này"</string> - <string name="enable_adb" msgid="7982306934419797485">"Gỡ lỗi USB"</string> + <string name="enable_adb" msgid="7982306934419797485">"Gỡ lỗi qua USB"</string> <string name="enable_adb_summary" msgid="4881186971746056635">"Bật chế độ gỡ lỗi khi kết nối USB"</string> <string name="clear_adb_keys" msgid="4038889221503122743">"Thu hồi ủy quyền gỡ lỗi USB"</string> <string name="bugreport_in_power" msgid="7923901846375587241">"Phím tắt báo cáo lỗi"</string> @@ -263,7 +263,7 @@ <string name="debug_view_attributes" msgid="6485448367803310384">"Cho phép kiểm tra thuộc tính của chế độ xem"</string> <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Luôn bật dữ liệu di động ngay cả khi Wi-Fi đang hoạt động (để chuyển đổi mạng nhanh)."</string> <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Sử dụng tính năng tăng tốc phần cứng khi chia sẻ kết nối nếu có"</string> - <string name="adb_warning_title" msgid="6234463310896563253">"Cho phép gỡ lỗi USB?"</string> + <string name="adb_warning_title" msgid="6234463310896563253">"Cho phép gỡ lỗi qua USB?"</string> <string name="adb_warning_message" msgid="7316799925425402244">"Gỡ lỗi USB chỉ dành cho mục đích phát triển. Hãy sử dụng tính năng này để sao chép dữ liệu giữa máy tính và thiết bị của bạn, cài đặt ứng dụng trên thiết bị của bạn mà không thông báo và đọc dữ liệu nhật ký."</string> <string name="adb_keys_warning_message" msgid="5659849457135841625">"Thu hồi quyền truy cập gỡ lỗi USB từ tất cả máy tính mà bạn đã ủy quyền trước đó?"</string> <string name="dev_settings_warning_title" msgid="7244607768088540165">"Cho phép cài đặt phát triển?"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index e85199f9ca0d..c64130210d37 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -329,7 +329,7 @@ <string name="show_all_anrs" msgid="4924885492787069007">"顯示背景 ANR"</string> <string name="show_all_anrs_summary" msgid="6636514318275139826">"為背景應用程式顯示「應用程式無回應」對話方塊"</string> <string name="show_notification_channel_warnings" msgid="1399948193466922683">"顯示通知管道警告"</string> - <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"當應用程式未經有效管道發佈通知時,在畫面上顯示警告"</string> + <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"當應用程式未經有效管道發布通知時,在畫面上顯示警告"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"強制允許將應用程式寫入外部儲存空間"</string> <string name="force_allow_on_external_summary" msgid="3640752408258034689">"允許將任何應用程式寫入外部儲存空間 (無論資訊清單值為何)"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"將活動強制設為可調整大小"</string> diff --git a/packages/SoundPicker/res/layout-watch/radio_with_work_badge.xml b/packages/SoundPicker/res/layout-watch/radio_with_work_badge.xml index 0e11621e5f4d..ee29a3710143 100644 --- a/packages/SoundPicker/res/layout-watch/radio_with_work_badge.xml +++ b/packages/SoundPicker/res/layout-watch/radio_with_work_badge.xml @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. --> -<com.android.providers.media.CheckedListItem xmlns:android="http://schemas.android.com/apk/res/android" +<com.android.soundpicker.CheckedListItem xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_vertical" @@ -44,4 +44,4 @@ android:layout_centerVertical="true" android:scaleType="centerCrop" android:layout_marginRight="20dp" /> -</com.android.providers.media.CheckedListItem> +</com.android.soundpicker.CheckedListItem> diff --git a/packages/SoundPicker/res/layout/radio_with_work_badge.xml b/packages/SoundPicker/res/layout/radio_with_work_badge.xml index e7d37eab205c..c8ca231f27a4 100644 --- a/packages/SoundPicker/res/layout/radio_with_work_badge.xml +++ b/packages/SoundPicker/res/layout/radio_with_work_badge.xml @@ -14,7 +14,7 @@ limitations under the License. --> -<com.android.providers.media.CheckedListItem xmlns:android="http://schemas.android.com/apk/res/android" +<com.android.soundpicker.CheckedListItem xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_vertical" @@ -45,4 +45,4 @@ android:layout_centerVertical="true" android:scaleType="centerCrop" android:layout_marginRight="20dp" /> -</com.android.providers.media.CheckedListItem> +</com.android.soundpicker.CheckedListItem> diff --git a/packages/SoundPicker/src/com/android/soundpicker/CheckedListItem.java b/packages/SoundPicker/src/com/android/soundpicker/CheckedListItem.java new file mode 100644 index 000000000000..bde87cfc39ef --- /dev/null +++ b/packages/SoundPicker/src/com/android/soundpicker/CheckedListItem.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.soundpicker; + +import android.content.Context; +import android.widget.Checkable; +import android.widget.CheckedTextView; +import android.widget.RelativeLayout; +import android.util.AttributeSet; + +/** + * The {@link CheckedListItem} is a layout item that represents a ringtone, and is used in + * {@link RingtonePickerActivity}. It contains the ringtone's name, and a work badge to right of the + * name if the ringtone belongs to a work profile. + */ +public class CheckedListItem extends RelativeLayout implements Checkable { + + public CheckedListItem(Context context) { + super(context); + } + + public CheckedListItem(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public CheckedListItem(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public CheckedListItem(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + public void setChecked(boolean checked) { + getCheckedTextView().setChecked(checked); + } + + @Override + public boolean isChecked() { + return getCheckedTextView().isChecked(); + } + + @Override + public void toggle() { + getCheckedTextView().toggle(); + } + + private CheckedTextView getCheckedTextView() { + return (CheckedTextView) findViewById(R.id.checked_text_view); + } + +} diff --git a/packages/services/PacProcessor/Android.bp b/packages/services/PacProcessor/Android.bp index 93b2d956cf6f..494a8187886d 100644 --- a/packages/services/PacProcessor/Android.bp +++ b/packages/services/PacProcessor/Android.bp @@ -21,3 +21,9 @@ android_app { certificate: "platform", jni_libs: ["libjni_pacprocessor"], } + +filegroup { + name: "PacProcessor-aidl-sources", + srcs: ["src/**/*.aidl"], + path: "src", +} diff --git a/packages/services/PacProcessor/com/android/net/IProxyService.aidl b/packages/services/PacProcessor/src/com/android/net/IProxyService.aidl index 4e54aba5c3bf..4e54aba5c3bf 100644 --- a/packages/services/PacProcessor/com/android/net/IProxyService.aidl +++ b/packages/services/PacProcessor/src/com/android/net/IProxyService.aidl diff --git a/packages/services/Proxy/Android.bp b/packages/services/Proxy/Android.bp index 87aa7637df8e..d93c9f8d9941 100644 --- a/packages/services/Proxy/Android.bp +++ b/packages/services/Proxy/Android.bp @@ -5,3 +5,9 @@ android_app { certificate: "platform", privileged: true, } + +filegroup { + name: "ProxyHandler-aidl-sources", + srcs: ["src/**/*.aidl"], + path: "src", +} diff --git a/packages/services/Proxy/com/android/net/IProxyCallback.aidl b/packages/services/Proxy/src/com/android/net/IProxyCallback.aidl index 26b2a3f9da2d..26b2a3f9da2d 100644 --- a/packages/services/Proxy/com/android/net/IProxyCallback.aidl +++ b/packages/services/Proxy/src/com/android/net/IProxyCallback.aidl diff --git a/packages/services/Proxy/com/android/net/IProxyPortListener.aidl b/packages/services/Proxy/src/com/android/net/IProxyPortListener.aidl index fa4caf3dba91..fa4caf3dba91 100644 --- a/packages/services/Proxy/com/android/net/IProxyPortListener.aidl +++ b/packages/services/Proxy/src/com/android/net/IProxyPortListener.aidl diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java index 4facf4ea62a2..4151c7269934 100644 --- a/services/core/java/com/android/server/SystemService.java +++ b/services/core/java/com/android/server/SystemService.java @@ -54,6 +54,10 @@ import com.android.server.pm.UserManagerService; * {@hide} */ public abstract class SystemService { + + // TODO(b/133242016) STOPSHIP: change to false before R ships + protected static final boolean DEBUG_USER = true; + /* * Boot Phases */ @@ -150,7 +154,17 @@ public abstract class SystemService { public void onBootPhase(int phase) {} /** - * @deprecated subclasses should extend {@link #onStartUser(int, int)} instead (which by default + * Checks if the service should be available for the given user. + * + * <p>By default returns {@code true}, but subclasses should extend for optimization, if they + * don't support some types (like headless system user). + */ + public boolean isSupported(@NonNull UserInfo userInfo) { + return true; + } + + /** + * @deprecated subclasses should extend {@link #onStartUser(UserInfo)} instead (which by default * calls this method). */ @Deprecated @@ -160,6 +174,9 @@ public abstract class SystemService { * Called when a new user is starting, for system services to initialize any per-user * state they maintain for running users. * + * <p>This method is only called when the service {@link #isSupported(UserInfo) supports} this + * user. + * * @param userInfo The information about the user. <b>NOTE: </b> this is a "live" object * referenced by {@link UserManagerService} and hence should not be modified. */ @@ -168,7 +185,7 @@ public abstract class SystemService { } /** - * @deprecated subclasses should extend {@link #onUnlockUser(int, int)} instead (which by + * @deprecated subclasses should extend {@link #onUnlockUser(UserInfo)} instead (which by * default calls this method). */ @Deprecated @@ -185,6 +202,9 @@ public abstract class SystemService { * Code written inside system services should use * {@link UserManager#isUserUnlockingOrUnlocked(int)} to handle both of * these states. + * <p> + * This method is only called when the service {@link #isSupported(UserInfo) supports} this + * user. * * @param userInfo The information about the user. <b>NOTE: </b> this is a "live" object * referenced by {@link UserManagerService} and hence should not be modified. @@ -194,8 +214,8 @@ public abstract class SystemService { } /** - * @deprecated subclasses should extend {@link #onSwitchUser(int, int)} instead (which by - * default calls this method). + * @deprecated subclasses should extend {@link #onSwitchUser(UserInfo, UserInfo)} instead + * (which by default calls this method). */ @Deprecated public void onSwitchUser(@UserIdInt int userHandle) {} @@ -205,15 +225,21 @@ public abstract class SystemService { * special behavior for whichever user is currently in the foreground. This is called * before any application processes are aware of the new user. * - * @param userInfo The information about the user. <b>NOTE: </b> this is a "live" object + * <p>This method is only called when the service {@link #isSupported(UserInfo) supports} either + * of the users ({@code from} or {@code to}). + * + * <b>NOTE: </b> both {@code from} and {@code to} are "live" objects * referenced by {@link UserManagerService} and hence should not be modified. + * + * @param from The information about the user being switched from. + * @param to The information about the user being switched from to. */ - public void onSwitchUser(@NonNull UserInfo userInfo) { - onSwitchUser(userInfo.id); + public void onSwitchUser(@NonNull UserInfo from, @NonNull UserInfo to) { + onSwitchUser(to.id); } /** - * @deprecated subclasses should extend {@link #onStopUser(int, int)} instead (which by default + * @deprecated subclasses should extend {@link #onStopUser(UserInfo)} instead (which by default * calls this method). */ @Deprecated @@ -225,6 +251,9 @@ public abstract class SystemService { * broadcast to the user; it is a good place to stop making use of any resources of that * user (such as binding to a service running in the user). * + * <p>This method is only called when the service {@link #isSupported(UserInfo) supports} this + * user. + * * <p>NOTE: This is the last callback where the callee may access the target user's CE storage. * * @param userInfo The information about the user. <b>NOTE: </b> this is a "live" object @@ -235,7 +264,7 @@ public abstract class SystemService { } /** - * @deprecated subclasses should extend {@link #onCleanupUser(int, int)} instead (which by + * @deprecated subclasses should extend {@link #onCleanupUser(UserInfo)} instead (which by * default calls this method). */ @Deprecated @@ -246,8 +275,12 @@ public abstract class SystemService { * state they maintain for running users. This is called after all application process * teardown of the user is complete. * + * <p>This method is only called when the service {@link #isSupported(UserInfo) supports} this + * user. + * * <p>NOTE: When this callback is called, the CE storage for the target user may not be - * accessible already. Use {@link #onCleanupUser} instead if you need to access the CE storage. + * accessible already. Use {@link #onStopUser(UserInfo)} instead if you need to access the CE + * storage. * * @param userInfo The information about the user. <b>NOTE: </b> this is a "live" object * referenced by {@link UserManagerService} and hence should not be modified. diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java index b085946899bd..c7157981ada2 100644 --- a/services/core/java/com/android/server/SystemServiceManager.java +++ b/services/core/java/com/android/server/SystemServiceManager.java @@ -23,6 +23,7 @@ import android.content.pm.UserInfo; import android.os.Environment; import android.os.SystemClock; import android.os.Trace; +import android.os.UserHandle; import android.os.UserManagerInternal; import android.util.Slog; @@ -41,8 +42,16 @@ import java.util.ArrayList; */ public class SystemServiceManager { private static final String TAG = "SystemServiceManager"; + private static final boolean DEBUG = false; private static final int SERVICE_CALL_WARN_TIME_MS = 50; + // Constants used on onUser(...) + private static final String START = "Start"; + private static final String UNLOCK = "Unlock"; + private static final String SWITCH = "Switch"; + private static final String STOP = "Stop"; + private static final String CLEANUP = "Cleanup"; + private static File sSystemDir; private final Context mContext; private boolean mSafeMode; @@ -90,7 +99,6 @@ public class SystemServiceManager { * @return The service instance, never null. * @throws RuntimeException if the service fails to start. */ - @SuppressWarnings("unchecked") public <T extends SystemService> T startService(Class<T> serviceClass) { try { final String name = serviceClass.getName(); @@ -212,64 +220,104 @@ public class SystemServiceManager { * Starts the given user. */ public void startUser(final @NonNull TimingsTraceAndSlog t, final @UserIdInt int userHandle) { - onUser(t, "Start", userHandle, (s, u) -> s.onStartUser(u)); + onUser(t, START, userHandle); } /** * Unlocks the given user. */ public void unlockUser(final @UserIdInt int userHandle) { - onUser("Unlock", userHandle, (s, u) -> s.onUnlockUser(u)); + onUser(UNLOCK, userHandle); } /** * Switches to the given user. */ - public void switchUser(final @UserIdInt int userHandle) { - onUser("Switch", userHandle, (s, u) -> s.onSwitchUser(u)); + public void switchUser(final @UserIdInt int from, final @UserIdInt int to) { + onUser(TimingsTraceAndSlog.newAsyncLog(), SWITCH, to, from); } /** * Stops the given user. */ public void stopUser(final @UserIdInt int userHandle) { - onUser("Stop", userHandle, (s, u) -> s.onStopUser(u)); + onUser(STOP, userHandle); } /** * Cleans up the given user. */ public void cleanupUser(final @UserIdInt int userHandle) { - onUser("Cleanup", userHandle, (s, u) -> s.onCleanupUser(u)); + onUser(CLEANUP, userHandle); } - private interface ServiceVisitor { - void visit(@NonNull SystemService service, @NonNull UserInfo userInfo); + private void onUser(@NonNull String onWhat, @UserIdInt int userHandle) { + onUser(TimingsTraceAndSlog.newAsyncLog(), onWhat, userHandle); } - private void onUser(@NonNull String onWhat, @UserIdInt int userHandle, - @NonNull ServiceVisitor visitor) { - onUser(TimingsTraceAndSlog.newAsyncLog(), onWhat, userHandle, visitor); + private void onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat, + @UserIdInt int userHandle) { + onUser(t, onWhat, userHandle, UserHandle.USER_NULL); } private void onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat, - @UserIdInt int userHandle, @NonNull ServiceVisitor visitor) { - t.traceBegin("ssm." + onWhat + "User-" + userHandle); - Slog.i(TAG, "Calling on" + onWhat + "User u" + userHandle); - final UserInfo userInfo = getUserInfo(userHandle); + @UserIdInt int curUserId, @UserIdInt int prevUserId) { + t.traceBegin("ssm." + onWhat + "User-" + curUserId); + Slog.i(TAG, "Calling on" + onWhat + "User " + curUserId); + final UserInfo curUserInfo = getUserInfo(curUserId); + final UserInfo prevUserInfo = prevUserId == UserHandle.USER_NULL ? null + : getUserInfo(prevUserId); final int serviceLen = mServices.size(); for (int i = 0; i < serviceLen; i++) { final SystemService service = mServices.get(i); final String serviceName = service.getClass().getName(); - t.traceBegin("ssm.on" + onWhat + "User-" + userHandle + " " + serviceName); + boolean supported = service.isSupported(curUserInfo); + + // Must check if either curUser or prevUser is supported (for example, if switching from + // unsupported to supported, we still need to notify the services) + if (!supported && prevUserInfo != null) { + supported = service.isSupported(prevUserInfo); + } + + if (!supported) { + if (DEBUG) { + Slog.d(TAG, "Skipping " + onWhat + "User-" + curUserId + " on service " + + serviceName + " because it's not supported (curUser: " + + curUserInfo + ", prevUser:" + prevUserInfo + ")"); + } else { + Slog.i(TAG, "Skipping " + onWhat + "User-" + curUserId + " on " + + serviceName); + } + continue; + } + t.traceBegin("ssm.on" + onWhat + "User-" + curUserId + " " + serviceName); long time = SystemClock.elapsedRealtime(); try { - visitor.visit(service, userInfo); + switch (onWhat) { + case SWITCH: + service.onSwitchUser(prevUserInfo, curUserInfo); + break; + case START: + service.onStartUser(curUserInfo); + break; + case UNLOCK: + service.onUnlockUser(curUserInfo); + break; + case STOP: + service.onStopUser(curUserInfo); + break; + case CLEANUP: + service.onCleanupUser(curUserInfo); + break; + default: + throw new IllegalArgumentException(onWhat + " what?"); + } } catch (Exception ex) { - Slog.wtf(TAG, "Failure reporting " + onWhat + " of user " + userHandle + Slog.wtf(TAG, "Failure reporting " + onWhat + " of user " + curUserInfo + " to service " + serviceName, ex); } - warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "on" + onWhat + "User "); + warnIfTooLong(SystemClock.elapsedRealtime() - time, service, + "on" + onWhat + "User-" + curUserId); t.traceEnd(); // what on service } t.traceEnd(); // main entry diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index d4ceb5a86946..b2c40ef897aa 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -2180,7 +2180,7 @@ class UserController implements Handler.Callback { BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START, Integer.toString(msg.arg1), msg.arg1); - mInjector.getSystemServiceManager().switchUser(msg.arg1); + mInjector.getSystemServiceManager().switchUser(msg.arg2, msg.arg1); break; case FOREGROUND_PROFILE_CHANGED_MSG: dispatchForegroundProfileChanged(msg.arg1); diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 4f33ebb035da..c466640e658b 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -2020,6 +2020,10 @@ public final class DisplayManagerService extends SystemService { @Override // Binder call public void resizeVirtualDisplay(IVirtualDisplayCallback callback, int width, int height, int densityDpi) { + if (width <= 0 || height <= 0 || densityDpi <= 0) { + throw new IllegalArgumentException("width, height, and densityDpi must be " + + "greater than 0"); + } final long token = Binder.clearCallingIdentity(); try { resizeVirtualDisplayInternal(callback.asBinder(), width, height, densityDpi); diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java index 9e3401882f45..e753a7be99f6 100644 --- a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java +++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java @@ -43,7 +43,7 @@ import java.util.Objects; * Maintains a connection to a particular media route provider service. */ final class MediaRoute2ProviderProxy implements ServiceConnection { - private static final String TAG = "MediaRoute2ProviderProxy"; + private static final String TAG = "MediaRoute2Provider"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final Context mContext; @@ -54,7 +54,6 @@ final class MediaRoute2ProviderProxy implements ServiceConnection { private Callback mCallback; - //TODO: make it nonnull private MediaRoute2ProviderInfo mProviderInfo; // Connection state @@ -246,13 +245,21 @@ final class MediaRoute2ProviderProxy implements ServiceConnection { if (mActiveConnection != connection) { return; } - // Set a unique provider id for identifying providers. - mProviderInfo = new MediaRoute2ProviderInfo.Builder(info) - .setUniqueId(mUniqueId) - .build(); if (DEBUG) { Slog.d(TAG, this + ": State changed "); } + setAndNotifyProviderInfo(info); + } + + private void setAndNotifyProviderInfo(MediaRoute2ProviderInfo info) { + //TODO: check if info is not updated + if (info == null) { + mProviderInfo = null; + } else { + mProviderInfo = new MediaRoute2ProviderInfo.Builder(info) + .setUniqueId(mUniqueId) + .build(); + } mHandler.post(mStateChanged); } @@ -261,6 +268,7 @@ final class MediaRoute2ProviderProxy implements ServiceConnection { mConnectionReady = false; mActiveConnection.dispose(); mActiveConnection = null; + setAndNotifyProviderInfo(null); } } @@ -337,7 +345,7 @@ final class MediaRoute2ProviderProxy implements ServiceConnection { mHandler.post(() -> onConnectionDied(Connection.this)); } - void postProviderUpdated(MediaRoute2ProviderInfo info) { + void postProviderInfoUpdated(MediaRoute2ProviderInfo info) { mHandler.post(() -> onProviderInfoUpdated(Connection.this, info)); } } @@ -354,10 +362,10 @@ final class MediaRoute2ProviderProxy implements ServiceConnection { } @Override - public void notifyProviderInfoUpdated(MediaRoute2ProviderInfo info) { + public void updateProviderInfo(MediaRoute2ProviderInfo info) { Connection connection = mConnectionRef.get(); if (connection != null) { - connection.postProviderUpdated(info); + connection.postProviderInfoUpdated(info); } } } diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 12137fe8d841..043c834230d1 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -33,6 +33,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; +import android.os.UserHandle; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; @@ -72,21 +73,20 @@ class MediaRouter2ServiceImpl { mContext = context; } - public void registerClientAsUser(@NonNull IMediaRouter2Client client, - @NonNull String packageName, int userId) { + public void registerClient(@NonNull IMediaRouter2Client client, + @NonNull String packageName) { Objects.requireNonNull(client, "client must not be null"); final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); - final int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId, - false /*allowAll*/, true /*requireFull*/, "registerClientAsUser", packageName); + final int userId = UserHandle.getUserId(uid); final boolean trusted = mContext.checkCallingOrSelfPermission( android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) == PackageManager.PERMISSION_GRANTED; final long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { - registerClientLocked(client, uid, pid, packageName, resolvedUserId, trusted); + registerClientLocked(client, uid, pid, packageName, userId, trusted); } } finally { Binder.restoreCallingIdentity(token); @@ -106,20 +106,20 @@ class MediaRouter2ServiceImpl { } } - public void registerManagerAsUser(@NonNull IMediaRouter2Manager manager, - @NonNull String packageName, int userId) { + public void registerManager(@NonNull IMediaRouter2Manager manager, + @NonNull String packageName) { Objects.requireNonNull(manager, "manager must not be null"); //TODO: should check permission final boolean trusted = true; final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); - final int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId, - false /*allowAll*/, true /*requireFull*/, "registerManagerAsUser", packageName); + final int userId = UserHandle.getUserId(uid); + final long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { - registerManagerLocked(manager, uid, pid, packageName, resolvedUserId, trusted); + registerManagerLocked(manager, uid, pid, packageName, userId, trusted); } } finally { Binder.restoreCallingIdentity(token); @@ -254,6 +254,10 @@ class MediaRouter2ServiceImpl { userRecord.mClientRecords.add(clientRecord); mAllClientRecords.put(binder, clientRecord); + + userRecord.mHandler.sendMessage( + obtainMessage(UserHandler::notifyProviderInfosUpdatedToClient, + userRecord.mHandler, client)); } } @@ -341,9 +345,9 @@ class MediaRouter2ServiceImpl { userRecord.mManagerRecords.add(managerRecord); mAllManagerRecords.put(binder, managerRecord); - //TODO: remove this when it's unnecessary - // Sends published routes to newly added manager. - userRecord.mHandler.scheduleUpdateManagerState(); + userRecord.mHandler.sendMessage( + obtainMessage(UserHandler::notifyProviderInfosUpdatedToManager, + userRecord.mHandler, manager)); final int count = userRecord.mClientRecords.size(); for (int i = 0; i < count; i++) { @@ -504,14 +508,14 @@ class MediaRouter2ServiceImpl { private final WeakReference<MediaRouter2ServiceImpl> mServiceRef; private final UserRecord mUserRecord; private final MediaRoute2ProviderWatcher mWatcher; - private final ArrayList<IMediaRouter2Manager> mTempManagers = new ArrayList<>(); //TODO: Make this thread-safe. private final ArrayList<MediaRoute2ProviderProxy> mMediaProviders = new ArrayList<>(); + private List<MediaRoute2ProviderInfo> mProviderInfos; private boolean mRunning; - private boolean mManagerStateUpdateScheduled; + private boolean mProviderInfosUpdateScheduled; UserHandler(MediaRouter2ServiceImpl service, UserRecord userRecord) { super(Looper.getMainLooper(), null, true); @@ -553,14 +557,14 @@ class MediaRouter2ServiceImpl { } private void updateProvider(MediaRoute2ProviderProxy provider) { - scheduleUpdateManagerState(); + scheduleUpdateProviderInfos(); } private void selectRoute(ClientRecord clientRecord, MediaRoute2Info route) { if (route != null) { MediaRoute2ProviderProxy provider = findProvider(route.getProviderId()); if (provider == null) { - Log.w(TAG, "Ignoring to select route of unknown provider " + route); + Slog.w(TAG, "Ignoring to select route of unknown provider " + route); } else { provider.selectRoute(clientRecord.mPackageName, route.getId()); } @@ -571,7 +575,7 @@ class MediaRouter2ServiceImpl { if (route != null) { MediaRoute2ProviderProxy provider = findProvider(route.getProviderId()); if (provider == null) { - Log.w(TAG, "Ignoring to unselect route of unknown provider " + route); + Slog.w(TAG, "Ignoring to unselect route of unknown provider " + route); } else { provider.unselectRoute(clientRecord.mPackageName, route.getId()); } @@ -585,49 +589,71 @@ class MediaRouter2ServiceImpl { } } - private void scheduleUpdateManagerState() { - if (!mManagerStateUpdateScheduled) { - mManagerStateUpdateScheduled = true; - sendMessage(PooledLambda.obtainMessage(UserHandler::updateManagerState, this)); + private void scheduleUpdateProviderInfos() { + if (!mProviderInfosUpdateScheduled) { + mProviderInfosUpdateScheduled = true; + sendMessage(PooledLambda.obtainMessage(UserHandler::updateProviderInfos, this)); } } - private void updateManagerState() { - mManagerStateUpdateScheduled = false; + private void updateProviderInfos() { + mProviderInfosUpdateScheduled = false; MediaRouter2ServiceImpl service = mServiceRef.get(); if (service == null) { return; } - //TODO: Consider using a member variable (like mTempManagers). + final List<IMediaRouter2Manager> managers = new ArrayList<>(); + final List<IMediaRouter2Client> clients = new ArrayList<>(); final List<MediaRoute2ProviderInfo> providers = new ArrayList<>(); for (MediaRoute2ProviderProxy mediaProvider : mMediaProviders) { final MediaRoute2ProviderInfo providerInfo = mediaProvider.getProviderInfo(); if (providerInfo == null || !providerInfo.isValid()) { - Log.w(TAG, "Ignoring invalid provider info : " + providerInfo); + Slog.w(TAG, "Ignoring invalid provider info : " + providerInfo); } else { providers.add(providerInfo); } } + mProviderInfos = providers; - try { - synchronized (service.mLock) { - final int count = mUserRecord.mManagerRecords.size(); - for (int i = 0; i < count; i++) { - mTempManagers.add(mUserRecord.mManagerRecords.get(i).mManager); - } + synchronized (service.mLock) { + for (ManagerRecord managerRecord : mUserRecord.mManagerRecords) { + managers.add(managerRecord.mManager); } - for (IMediaRouter2Manager tempManager : mTempManagers) { - try { - tempManager.notifyProviderInfosUpdated(providers); - } catch (RemoteException ex) { - Slog.w(TAG, "Failed to update manager state. Manager probably died.", ex); - } + for (ClientRecord clientRecord : mUserRecord.mClientRecords) { + clients.add(clientRecord.mClient); } - } finally { - // Clear the list in preparation for the next time. - mTempManagers.clear(); + } + for (IMediaRouter2Manager manager : managers) { + notifyProviderInfosUpdatedToManager(manager); + } + for (IMediaRouter2Client client : clients) { + notifyProviderInfosUpdatedToClient(client); + } + } + + private void notifyProviderInfosUpdatedToClient(IMediaRouter2Client client) { + if (mProviderInfos == null) { + scheduleUpdateProviderInfos(); + return; + } + try { + client.notifyProviderInfosUpdated(mProviderInfos); + } catch (RemoteException ex) { + Slog.w(TAG, "Failed to notify provider infos updated. Client probably died."); + } + } + + private void notifyProviderInfosUpdatedToManager(IMediaRouter2Manager manager) { + if (mProviderInfos == null) { + scheduleUpdateProviderInfos(); + return; + } + try { + manager.notifyProviderInfosUpdated(mProviderInfos); + } catch (RemoteException ex) { + Slog.w(TAG, "Failed to notify provider infos updated. Manager probably died."); } } diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java index a43068b87c06..2670cd8247ac 100644 --- a/services/core/java/com/android/server/media/MediaRouterService.java +++ b/services/core/java/com/android/server/media/MediaRouterService.java @@ -435,12 +435,12 @@ public final class MediaRouterService extends IMediaRouterService.Stub // Binder call @Override - public void registerClient2AsUser(IMediaRouter2Client client, String packageName, int userId) { + public void registerClient2(IMediaRouter2Client client, String packageName) { final int uid = Binder.getCallingUid(); if (!validatePackageName(uid, packageName)) { throw new SecurityException("packageName must match the calling uid"); } - mService2.registerClientAsUser(client, packageName, userId); + mService2.registerClient(client, packageName); } // Binder call @@ -464,13 +464,12 @@ public final class MediaRouterService extends IMediaRouterService.Stub // Binder call @Override - public void registerManagerAsUser(IMediaRouter2Manager manager, - String packageName, int userId) { + public void registerManager(IMediaRouter2Manager manager, String packageName) { final int uid = Binder.getCallingUid(); if (!validatePackageName(uid, packageName)) { throw new SecurityException("packageName must match the calling uid"); } - mService2.registerManagerAsUser(manager, packageName, userId); + mService2.registerManager(manager, packageName); } // Binder call diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index a1b6d492a4a3..1da5bc6c26ee 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -38,6 +38,7 @@ import android.sysprop.ApexProperties; import android.util.Slog; import com.android.internal.annotations.GuardedBy; +import com.android.internal.os.BackgroundThread; import com.android.internal.util.IndentingPrintWriter; import java.io.File; @@ -263,7 +264,8 @@ abstract class ApexManager { populateAllPackagesCacheIfNeeded(); mContext.unregisterReceiver(this); } - }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED)); + }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED), /* broadcastPermission */ null, + BackgroundThread.getHandler()); } private void populateAllPackagesCacheIfNeeded() { diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java index 77bf930fb4d7..712012d9e621 100644 --- a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java +++ b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java @@ -24,20 +24,17 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; -import android.os.Debug; import android.provider.Settings; -import android.telecom.TelecomManager; import android.text.TextUtils; -import android.util.Log; import android.util.Slog; +import com.android.internal.R; import com.android.internal.telephony.SmsApplication; import com.android.internal.util.CollectionUtils; import com.android.server.LocalServices; import com.android.server.role.RoleManagerService; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; @@ -67,14 +64,25 @@ public class LegacyRoleResolutionPolicy implements RoleManagerService.RoleHolder public List<String> getRoleHolders(@NonNull String roleName, @UserIdInt int userId) { switch (roleName) { case RoleManager.ROLE_ASSISTANT: { - String legacyAssistant = Settings.Secure.getStringForUser( - mContext.getContentResolver(), Settings.Secure.ASSISTANT, userId); - if (legacyAssistant == null || legacyAssistant.isEmpty()) { - return Collections.emptyList(); + String packageName; + String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), + Settings.Secure.ASSISTANT, userId); + // AssistUtils was using the default assistant app if Settings.Secure.ASSISTANT is + // null, while only an empty string means user selected "None". + if (setting != null) { + if (!setting.isEmpty()) { + ComponentName componentName = ComponentName.unflattenFromString(setting); + packageName = componentName != null ? componentName.getPackageName() : null; + } else { + packageName = null; + } + } else if (mContext.getPackageManager().isDeviceUpgrading()) { + String defaultAssistant = mContext.getString(R.string.config_defaultAssistant); + packageName = !TextUtils.isEmpty(defaultAssistant) ? defaultAssistant : null; } else { - return Collections.singletonList( - ComponentName.unflattenFromString(legacyAssistant).getPackageName()); + packageName = null; } + return CollectionUtils.singletonOrEmpty(packageName); } case RoleManager.ROLE_BROWSER: { PackageManagerInternal packageManagerInternal = LocalServices.getService( @@ -84,44 +92,36 @@ public class LegacyRoleResolutionPolicy implements RoleManagerService.RoleHolder return CollectionUtils.singletonOrEmpty(packageName); } case RoleManager.ROLE_DIALER: { - String setting = Settings.Secure.getStringForUser( - mContext.getContentResolver(), + String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), Settings.Secure.DIALER_DEFAULT_APPLICATION, userId); - return CollectionUtils.singletonOrEmpty(!TextUtils.isEmpty(setting) - ? setting - : mContext.getSystemService(TelecomManager.class).getSystemDialerPackage()); + String packageName; + if (!TextUtils.isEmpty(setting)) { + packageName = setting; + } else if (mContext.getPackageManager().isDeviceUpgrading()) { + // DefaultDialerManager was using the default dialer app if + // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid. + // TelecomManager.getSystemDialerPackage() won't work because it might not + // be ready. + packageName = mContext.getString(R.string.config_defaultDialer); + } else { + packageName = null; + } + return CollectionUtils.singletonOrEmpty(packageName); } case RoleManager.ROLE_SMS: { - // Moved over from SmsApplication#getApplication - String result = Settings.Secure.getStringForUser( - mContext.getContentResolver(), + String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), Settings.Secure.SMS_DEFAULT_APPLICATION, userId); - // TODO: STOPSHIP: Remove the following code once we read the value of - // config_defaultSms in RoleControllerService. - if (result == null) { - Collection<SmsApplication.SmsApplicationData> applications = - SmsApplication.getApplicationCollectionAsUser(mContext, userId); - SmsApplication.SmsApplicationData applicationData; - String defaultPackage = mContext.getResources() - .getString(com.android.internal.R.string.default_sms_application); - applicationData = - SmsApplication.getApplicationForPackage(applications, defaultPackage); - - if (applicationData == null) { - // Are there any applications? - if (applications.size() != 0) { - applicationData = - (SmsApplication.SmsApplicationData) applications.toArray()[0]; - } - } - if (DEBUG) { - Log.i(LOG_TAG, "Found default sms app: " + applicationData - + " among: " + applications + " from " + Debug.getCallers(4)); - } - SmsApplication.SmsApplicationData app = applicationData; - result = app == null ? null : app.mPackageName; + String packageName; + if (!TextUtils.isEmpty(setting)) { + packageName = setting; + } else if (mContext.getPackageManager().isDeviceUpgrading()) { + // SmsApplication was using the default SMS app if + // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid. + packageName = mContext.getString(R.string.config_defaultSms); + } else { + packageName = null; } - return CollectionUtils.singletonOrEmpty(result); + return CollectionUtils.singletonOrEmpty(packageName); } case RoleManager.ROLE_HOME: { PackageManager packageManager = mContext.getPackageManager(); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 4135ef3f2e0b..e851a06cbb85 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -796,10 +796,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mTmpApplySurfaceChangesTransactionState.obscured = true; } - mTmpApplySurfaceChangesTransactionState.displayHasContent |= - root.handleNotObscuredLocked(w, - mTmpApplySurfaceChangesTransactionState.obscured, - mTmpApplySurfaceChangesTransactionState.syswin); + final boolean displayHasContent = root.handleNotObscuredLocked(w, + mTmpApplySurfaceChangesTransactionState.obscured, + mTmpApplySurfaceChangesTransactionState.syswin); + + if (!mTmpApplySurfaceChangesTransactionState.displayHasContent + && !getDisplayPolicy().isWindowExcludedFromContent(w)) { + mTmpApplySurfaceChangesTransactionState.displayHasContent |= displayHasContent; + } if (w.mHasSurface && isDisplayed) { final int type = w.mAttrs.type; diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index e35ef258e96d..e5962ae19413 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -3790,6 +3790,20 @@ public class DisplayPolicy { mPointerLocationView = null; } + /** + * Check if the window could be excluded from checking if the display has content. + * + * @param w WindowState to check if should be excluded. + * @return True if the window type is PointerLocation which is excluded. + */ + boolean isWindowExcludedFromContent(WindowState w) { + if (w != null && mPointerLocationView != null) { + return w.mClient == mPointerLocationView.getWindowToken(); + } + + return false; + } + @VisibleForTesting static boolean isOverlappingWithNavBar(WindowState targetWindow, WindowState navBarWindow) { if (navBarWindow == null || !navBarWindow.isVisibleLw() diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index b2ac5490440d..6132cc2250b9 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -52,8 +52,9 @@ import android.os.Parcel; import android.os.RemoteCallback; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.os.Trace; import android.os.UserHandle; -import android.os.UserManager; +import android.os.UserManagerInternal; import android.provider.Settings; import android.service.voice.IVoiceInteractionService; import android.service.voice.IVoiceInteractionSession; @@ -95,14 +96,14 @@ import java.util.concurrent.Executor; */ public class VoiceInteractionManagerService extends SystemService { static final String TAG = "VoiceInteractionManagerService"; - static final boolean DEBUG = true; // TODO(b/133242016) STOPSHIP: change to false before R ships + static final boolean DEBUG = false; final Context mContext; final ContentResolver mResolver; final DatabaseHelper mDbHelper; final ActivityManagerInternal mAmInternal; final ActivityTaskManagerInternal mAtmInternal; - final UserManager mUserManager; + final UserManagerInternal mUserManagerInternal; final ArraySet<Integer> mLoadedKeyphraseIds = new ArraySet<>(); ShortcutServiceInternal mShortcutServiceInternal; SoundTriggerInternal mSoundTriggerInternal; @@ -120,8 +121,8 @@ public class VoiceInteractionManagerService extends SystemService { LocalServices.getService(ActivityManagerInternal.class)); mAtmInternal = Preconditions.checkNotNull( LocalServices.getService(ActivityTaskManagerInternal.class)); - mUserManager = Preconditions.checkNotNull( - context.getSystemService(UserManager.class)); + mUserManagerInternal = Preconditions.checkNotNull( + LocalServices.getService(UserManagerInternal.class)); PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService( PermissionManagerServiceInternal.class); @@ -157,37 +158,30 @@ public class VoiceInteractionManagerService extends SystemService { } @Override + public boolean isSupported(UserInfo userInfo) { + return userInfo.isFull(); + } + + @Override public void onStartUser(@NonNull UserInfo userInfo) { - if (DEBUG) Slog.d(TAG, "onStartUser(" + userInfo + ")"); + if (DEBUG_USER) Slog.d(TAG, "onStartUser(" + userInfo + ")"); - if (!userInfo.isFull()) { - if (DEBUG) Slog.d(TAG, "***** skipping on non-full user " + userInfo); - return; - } mServiceStub.initForUser(userInfo.id); } @Override public void onUnlockUser(@NonNull UserInfo userInfo) { - if (DEBUG) Slog.d(TAG, "onUnlockUser(" + userInfo + ")"); + if (DEBUG_USER) Slog.d(TAG, "onUnlockUser(" + userInfo + ")"); - if (!userInfo.isFull()) { - if (DEBUG) Slog.d(TAG, "***** skipping on non-full user " + userInfo); - return; - } mServiceStub.initForUser(userInfo.id); mServiceStub.switchImplementationIfNeeded(false); } @Override - public void onSwitchUser(@NonNull UserInfo userInfo) { - if (DEBUG) Slog.d(TAG, "onSwitchUser(" + userInfo + ")"); + public void onSwitchUser(@NonNull UserInfo from, @NonNull UserInfo to) { + if (DEBUG_USER) Slog.d(TAG, "onSwitchUser(" + from + " > " + to + ")"); - if (!userInfo.isFull()) { - if (DEBUG) Slog.d(TAG, "***** skipping on non-full user " + userInfo); - return; - } - mServiceStub.switchUser(userInfo.id); + mServiceStub.switchUser(to.id); } class LocalService extends VoiceInteractionManagerInternal { @@ -225,6 +219,7 @@ public class VoiceInteractionManagerService extends SystemService { private boolean mSafeMode; private int mCurUser; private boolean mCurUserUnlocked; + private boolean mCurUserSupported; private final boolean mEnableService; VoiceInteractionManagerServiceStub() { @@ -292,9 +287,9 @@ public class VoiceInteractionManagerService extends SystemService { public void initForUser(int userHandle) { final TimingsTraceAndSlog t; - if (DEBUG) { - t = TimingsTraceAndSlog.newAsyncLog(); - t.traceBegin("VoiceInteractionSvc.initForUser(" + userHandle + ")"); + if (DEBUG_USER) { + t = new TimingsTraceAndSlog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER); + t.traceBegin("initForUser(" + userHandle + ")"); } else { t = null; } @@ -439,15 +434,21 @@ public class VoiceInteractionManagerService extends SystemService { new SettingsObserver(UiThread.getHandler()); synchronized (this) { - mCurUser = ActivityManager.getCurrentUser(); + setCurrentUserLocked(ActivityManager.getCurrentUser()); switchImplementationIfNeededLocked(false); } } - public void switchUser(int userHandle) { + private void setCurrentUserLocked(@UserIdInt int userHandle) { + mCurUser = userHandle; + final UserInfo userInfo = mUserManagerInternal.getUserInfo(mCurUser); + mCurUserSupported = isSupported(userInfo); + } + + public void switchUser(@UserIdInt int userHandle) { FgThread.getHandler().post(() -> { synchronized (this) { - mCurUser = userHandle; + setCurrentUserLocked(userHandle); mCurUserUnlocked = false; switchImplementationIfNeededLocked(false); } @@ -461,10 +462,22 @@ public class VoiceInteractionManagerService extends SystemService { } void switchImplementationIfNeededLocked(boolean force) { + if (!mCurUserSupported) { + if (DEBUG_USER) { + Slog.d(TAG, "switchImplementationIfNeeded(): skipping on unsuported user " + + mCurUser); + } + if (mImpl != null) { + mImpl.shutdownLocked(); + setImplLocked(null); + } + return; + } + final TimingsTraceAndSlog t; - if (DEBUG) { - t = TimingsTraceAndSlog.newAsyncLog(); - t.traceBegin("VoiceInteractionSvc.switchImplementation(" + mCurUser + ")"); + if (DEBUG_USER) { + t = new TimingsTraceAndSlog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER); + t.traceBegin("switchImplementation(" + mCurUser + ")"); } else { t = null; } @@ -494,7 +507,7 @@ public class VoiceInteractionManagerService extends SystemService { final boolean hasComponent = serviceComponent != null && serviceInfo != null; - if (mUserManager.isUserUnlockingOrUnlocked(mCurUser)) { + if (mUserManagerInternal.isUserUnlockingOrUnlocked(mCurUser)) { if (hasComponent) { mShortcutServiceInternal.setShortcutHostPackage(TAG, serviceComponent.getPackageName(), mCurUser); @@ -1275,6 +1288,9 @@ public class VoiceInteractionManagerService extends SystemService { synchronized (this) { pw.println("VOICE INTERACTION MANAGER (dumpsys voiceinteraction)"); pw.println(" mEnableService: " + mEnableService); + pw.println(" mCurUser: " + mCurUser); + pw.println(" mCurUserUnlocked: " + mCurUserUnlocked); + pw.println(" mCurUserSupported: " + mCurUserSupported); if (mImpl == null) { pw.println(" (No active implementation)"); return; @@ -1330,9 +1346,12 @@ public class VoiceInteractionManagerService extends SystemService { RoleObserver(@NonNull @CallbackExecutor Executor executor) { mRm.addOnRoleHoldersChangedListenerAsUser(executor, this, UserHandle.ALL); - UserHandle currentUser = UserHandle.of(LocalServices.getService( - ActivityManagerInternal.class).getCurrentUserId()); - onRoleHoldersChanged(RoleManager.ROLE_ASSISTANT, currentUser); + // Sync only if assistant role has been initialized. + if (mRm.isRoleAvailable(RoleManager.ROLE_ASSISTANT)) { + UserHandle currentUser = UserHandle.of(LocalServices.getService( + ActivityManagerInternal.class).getCurrentUserId()); + onRoleHoldersChanged(RoleManager.ROLE_ASSISTANT, currentUser); + } } private @NonNull String getDefaultRecognizer(@NonNull UserHandle user) { diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java index 42a5501cc229..bf6c0197a468 100644 --- a/telephony/java/android/provider/Telephony.java +++ b/telephony/java/android/provider/Telephony.java @@ -4058,6 +4058,53 @@ public final class Telephony { public static final String DEFAULT_SORT_ORDER = DELIVERY_TIME + " DESC"; /** + * The Epoch Unix timestamp when the device received the message. + * <P>Type: INTEGER</P> + */ + public static final String RECEIVED_TIME = "received_time"; + + /** + * Indicates that whether the message has been broadcasted to the application. + * <P>Type: BOOLEAN</P> + */ + public static final String MESSAGE_BROADCASTED = "message_broadcasted"; + + /** + * The Warning Area Coordinates Elements. This element is used for geo-fencing purpose. + * + * The geometry and its coordinates are separated vertical bar, the first item is the + * geometry type and the remaining items are the parameter of this geometry. + * + * Only circle and polygon are supported. The coordinates are represented in Horizontal + * coordinates format. + * + * Coordinate encoding: + * "latitude, longitude" + * where -90.00000 <= latitude <= 90.00000 and -180.00000 <= longitude <= 180.00000 + * + * Polygon encoding: + * "polygon|lat1,lng1|lat2,lng2|...|latn,lngn" + * lat1,lng1 ... latn,lngn are the vertices coordinate of the polygon. + * + * Circle encoding: + * "circle|lat,lng|radius". + * lat,lng is the center of the circle. The unit of circle's radius is meter. + * + * Example: + * "circle|0,0|100" mean a circle which center located at (0,0) and its radius is 100 meter. + * "polygon|0,1.5|0,1|1,1|1,0" mean a polygon has vertices (0,1.5),(0,1),(1,1),(1,0). + * + * There could be more than one geometry store in this field, they are separated by a + * semicolon. + * + * Example: + * "circle|0,0|100;polygon|0,0|0,1.5|1,1|1,0;circle|100.123,100|200.123" + * + * <P>Type: TEXT</P> + */ + public static final String GEOMETRIES = "geometries"; + + /** * Query columns for instantiating {@link android.telephony.CellBroadcastMessage} objects. */ public static final String[] QUERY_COLUMNS = { diff --git a/telephony/java/com/android/internal/telephony/CbGeoUtils.java b/telephony/java/com/android/internal/telephony/CbGeoUtils.java new file mode 100644 index 000000000000..c973b672ae40 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/CbGeoUtils.java @@ -0,0 +1,359 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.telephony; + +import android.annotation.NonNull; +import android.telephony.Rlog; +import android.text.TextUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + + +/** + * This utils class is specifically used for geo-targeting of CellBroadcast messages. + * The coordinates used by this utils class are latitude and longitude, but some algorithms in this + * class only use them as coordinates on plane, so the calculation will be inaccurate. So don't use + * this class for anything other then geo-targeting of cellbroadcast messages. + */ +public class CbGeoUtils { + /** Geometric interface. */ + public interface Geometry { + /** + * Determines if the given point {@code p} is inside the geometry. + * @param p point in latitude, longitude format. + * @return {@code True} if the given point is inside the geometry. + */ + boolean contains(LatLng p); + } + + /** + * Tolerance for determining if the value is 0. If the absolute value of a value is less than + * this tolerance, it will be treated as 0. + */ + public static final double EPS = 1e-7; + + /** The radius of earth. */ + public static final int EARTH_RADIUS_METER = 6371 * 1000; + + private static final String TAG = "CbGeoUtils"; + + /** The identifier of geometry in the encoded string. */ + private static final String CIRCLE_SYMBOL = "circle"; + private static final String POLYGON_SYMBOL = "polygon"; + + /** Point represent by (latitude, longitude). */ + public static class LatLng { + public final double lat; + public final double lng; + + /** + * Constructor. + * @param lat latitude, range [-90, 90] + * @param lng longitude, range [-180, 180] + */ + public LatLng(double lat, double lng) { + this.lat = lat; + this.lng = lng; + } + + /** + * @param p the point use to calculate the subtraction result. + * @return the result of this point subtract the given point {@code p}. + */ + public LatLng subtract(LatLng p) { + return new LatLng(lat - p.lat, lng - p.lng); + } + + /** + * Calculate the distance in meter between this point and the given point {@code p}. + * @param p the point use to calculate the distance. + * @return the distance in meter. + */ + public double distance(LatLng p) { + double dlat = Math.sin(0.5 * Math.toRadians(lat - p.lat)); + double dlng = Math.sin(0.5 * Math.toRadians(lng - p.lng)); + double x = dlat * dlat + + dlng * dlng * Math.cos(Math.toRadians(lat)) * Math.cos(Math.toRadians(p.lat)); + return 2 * Math.atan2(Math.sqrt(x), Math.sqrt(1 - x)) * EARTH_RADIUS_METER; + } + } + + /** + * The class represents a simple polygon with at least 3 points. + */ + public static class Polygon implements Geometry { + /** + * In order to reduce the loss of precision in floating point calculations, all vertices + * of the polygon are scaled. Set the value of scale to 1000 can take into account the + * actual distance accuracy of 1 meter if the EPS is 1e-7 during the calculation. + */ + private static final double SCALE = 1000.0; + + private final List<LatLng> mVertices; + private final List<Point> mScaledVertices; + private final LatLng mOrigin; + + /** + * Constructs a simple polygon from the given vertices. The adjacent two vertices are + * connected to form an edge of the polygon. The polygon has at least 3 vertices, and the + * last vertices and the first vertices must be adjacent. + * + * The longitude difference in the vertices should be less than 180 degree. + */ + public Polygon(@NonNull List<LatLng> vertices) { + mVertices = vertices; + + // Find the point with smallest longitude as the mOrigin point. + int idx = 0; + for (int i = 1; i < vertices.size(); i++) { + if (vertices.get(i).lng < vertices.get(idx).lng) { + idx = i; + } + } + mOrigin = vertices.get(idx); + + mScaledVertices = vertices.stream() + .map(latLng -> convertAndScaleLatLng(latLng)) + .collect(Collectors.toList()); + } + + public List<LatLng> getVertices() { + return mVertices; + } + + /** + * Check if the given point {@code p} is inside the polygon. This method counts the number + * of times the polygon winds around the point P, A.K.A "winding number". The point is + * outside only when this "winding number" is 0. + * + * If a point is on the edge of the polygon, it is also considered to be inside the polygon. + */ + @Override + public boolean contains(LatLng latLng) { + Point p = convertAndScaleLatLng(latLng); + + int n = mScaledVertices.size(); + int windingNumber = 0; + for (int i = 0; i < n; i++) { + Point a = mScaledVertices.get(i); + Point b = mScaledVertices.get((i + 1) % n); + + // CCW is counterclockwise + // CCW = ab x ap + // CCW > 0 -> ap is on the left side of ab + // CCW == 0 -> ap is on the same line of ab + // CCW < 0 -> ap is on the right side of ab + int ccw = sign(crossProduct(b.subtract(a), p.subtract(a))); + + if (ccw == 0) { + if (Math.min(a.x, b.x) <= p.x && p.x <= Math.max(a.x, b.x) + && Math.min(a.y, b.y) <= p.y && p.y <= Math.max(a.y, b.y)) { + return true; + } + } else { + if (sign(a.y - p.y) <= 0) { + // upward crossing + if (ccw > 0 && sign(b.y - p.y) > 0) { + ++windingNumber; + } + } else { + // downward crossing + if (ccw < 0 && sign(b.y - p.y) <= 0) { + --windingNumber; + } + } + } + } + return windingNumber != 0; + } + + /** + * Move the given point {@code latLng} to the coordinate system with {@code mOrigin} as the + * origin and scale it. {@code mOrigin} is selected from the vertices of a polygon, it has + * the smallest longitude value among all of the polygon vertices. + * + * @param latLng the point need to be converted and scaled. + * @Return a {@link Point} object. + */ + private Point convertAndScaleLatLng(LatLng latLng) { + double x = latLng.lat - mOrigin.lat; + double y = latLng.lng - mOrigin.lng; + + // If the point is in different hemispheres(western/eastern) than the mOrigin, and the + // edge between them cross the 180th meridian, then its relative coordinates will be + // extended. + // For example, suppose the longitude of the mOrigin is -178, and the longitude of the + // point to be converted is 175, then the longitude after the conversion is -8. + // calculation: (-178 - 8) - (-178). + if (sign(mOrigin.lng) != 0 && sign(mOrigin.lng) != sign(latLng.lng)) { + double distCross0thMeridian = Math.abs(mOrigin.lng) + Math.abs(latLng.lng); + if (sign(distCross0thMeridian * 2 - 360) > 0) { + y = sign(mOrigin.lng) * (360 - distCross0thMeridian); + } + } + return new Point(x * SCALE, y * SCALE); + } + + private static double crossProduct(Point a, Point b) { + return a.x * b.y - a.y * b.x; + } + + static final class Point { + public final double x; + public final double y; + + Point(double x, double y) { + this.x = x; + this.y = y; + } + + public Point subtract(Point p) { + return new Point(x - p.x, y - p.y); + } + } + } + + /** The class represents a circle. */ + public static class Circle implements Geometry { + private final LatLng mCenter; + private final double mRadiusMeter; + + public Circle(LatLng center, double radiusMeter) { + this.mCenter = center; + this.mRadiusMeter = radiusMeter; + } + + public LatLng getCenter() { + return mCenter; + } + + public double getRadius() { + return mRadiusMeter; + } + + @Override + public boolean contains(LatLng p) { + return mCenter.distance(p) <= mRadiusMeter; + } + } + + /** + * Parse the geometries from the encoded string {@code str}. The string must follow the + * geometry encoding specified by {@link android.provider.Telephony.CellBroadcasts#GEOMETRIES}. + */ + @NonNull + public static List<Geometry> parseGeometriesFromString(@NonNull String str) { + List<Geometry> geometries = new ArrayList<>(); + for (String geometryStr : str.split("\\s*;\\s*")) { + String[] geoParameters = geometryStr.split("\\s*\\|\\s*"); + switch (geoParameters[0]) { + case CIRCLE_SYMBOL: + geometries.add(new Circle(parseLatLngFromString(geoParameters[1]), + Double.parseDouble(geoParameters[2]))); + break; + case POLYGON_SYMBOL: + List<LatLng> vertices = new ArrayList<>(geoParameters.length - 1); + for (int i = 1; i < geoParameters.length; i++) { + vertices.add(parseLatLngFromString(geoParameters[i])); + } + geometries.add(new Polygon(vertices)); + break; + default: + Rlog.e(TAG, "Invalid geometry format " + geometryStr); + } + } + return geometries; + } + + /** + * Encode a list of geometry objects to string. The encoding format is specified by + * {@link android.provider.Telephony.CellBroadcasts#GEOMETRIES}. + * + * @param geometries the list of geometry objects need to be encoded. + * @return the encoded string. + */ + @NonNull + public static String encodeGeometriesToString(@NonNull List<Geometry> geometries) { + return geometries.stream() + .map(geometry -> encodeGeometryToString(geometry)) + .filter(encodedStr -> !TextUtils.isEmpty(encodedStr)) + .collect(Collectors.joining(";")); + } + + + /** + * Encode the geometry object to string. The encoding format is specified by + * {@link android.provider.Telephony.CellBroadcasts#GEOMETRIES}. + * @param geometry the geometry object need to be encoded. + * @return the encoded string. + */ + @NonNull + private static String encodeGeometryToString(@NonNull Geometry geometry) { + StringBuilder sb = new StringBuilder(); + if (geometry instanceof Polygon) { + sb.append(POLYGON_SYMBOL); + for (LatLng latLng : ((Polygon) geometry).getVertices()) { + sb.append("|"); + sb.append(latLng.lat); + sb.append(","); + sb.append(latLng.lng); + } + } else if (geometry instanceof Circle) { + sb.append(CIRCLE_SYMBOL); + Circle circle = (Circle) geometry; + + // Center + sb.append("|"); + sb.append(circle.getCenter().lat); + sb.append(","); + sb.append(circle.getCenter().lng); + + // Radius + sb.append("|"); + sb.append(circle.getRadius()); + } else { + Rlog.e(TAG, "Unsupported geometry object " + geometry); + return null; + } + return sb.toString(); + } + + /** + * Parse {@link LatLng} from {@link String}. Latitude and longitude are separated by ",". + * Example: "13.56,-55.447". + * + * @param str encoded lat/lng string. + * @Return {@link LatLng} object. + */ + @NonNull + public static LatLng parseLatLngFromString(@NonNull String str) { + String[] latLng = str.split("\\s*,\\s*"); + return new LatLng(Double.parseDouble(latLng[0]), Double.parseDouble(latLng[1])); + } + + /** + * @Return the sign of the given value {@code value} with the specified tolerance. Return 1 + * means the sign is positive, -1 means negative, 0 means the value will be treated as 0. + */ + public static int sign(double value) { + if (value > EPS) return 1; + if (value < -EPS) return -1; + return 0; + } +} diff --git a/test-mock/Android.bp b/test-mock/Android.bp index 0129c4ca5bc1..9a653cf7204c 100644 --- a/test-mock/Android.bp +++ b/test-mock/Android.bp @@ -26,7 +26,6 @@ java_sdk_library { ], srcs_lib: "framework-minus-apex", - srcs_lib_whitelist_dirs: ["core/java"], srcs_lib_whitelist_pkgs: ["android"], compile_dex: true, } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index ca65736d8ec2..e9c24cd6e3e0 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -70,7 +70,6 @@ import java.lang.ref.WeakReference; import java.net.InetAddress; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -1170,15 +1169,16 @@ public class WifiManager { updateVerboseLoggingEnabledFromService(); } - private IWifiManager getIWifiManager() throws RemoteException { + private IWifiManager getIWifiManager() { if (mService == null) { synchronized (this) { mService = IWifiManager.Stub.asInterface( ServiceManager.getService(Context.WIFI_SERVICE)); - if (mService == null) { - throw new RemoteException("Wifi Service not running"); + if (mService != null) { + updateVerboseLoggingEnabledFromService(); + } else { + Log.e(TAG, "Wifi Service not running yet, ignoring WifiManager API call"); } - updateVerboseLoggingEnabledFromService(); } } return mService; @@ -1223,8 +1223,10 @@ public class WifiManager { @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE}) public List<WifiConfiguration> getConfiguredNetworks() { try { + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return Collections.emptyList(); ParceledListSlice<WifiConfiguration> parceledList = - getIWifiManager().getConfiguredNetworks(mContext.getOpPackageName()); + iWifiManager.getConfiguredNetworks(mContext.getOpPackageName()); if (parceledList == null) { return Collections.emptyList(); } @@ -1239,8 +1241,10 @@ public class WifiManager { @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE, READ_WIFI_CREDENTIAL}) public List<WifiConfiguration> getPrivilegedConfiguredNetworks() { try { + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return Collections.emptyList(); ParceledListSlice<WifiConfiguration> parceledList = - getIWifiManager().getPrivilegedConfiguredNetworks(mContext.getOpPackageName()); + iWifiManager.getPrivilegedConfiguredNetworks(mContext.getOpPackageName()); if (parceledList == null) { return Collections.emptyList(); } @@ -1271,14 +1275,16 @@ public class WifiManager { @NonNull List<ScanResult> scanResults) { List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> configs = new ArrayList<>(); try { + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return Collections.emptyList(); Map<String, Map<Integer, List<ScanResult>>> results = - getIWifiManager().getAllMatchingFqdnsForScanResults( + iWifiManager.getAllMatchingFqdnsForScanResults( scanResults); if (results.isEmpty()) { return configs; } List<WifiConfiguration> wifiConfigurations = - getIWifiManager().getWifiConfigsForPasspointProfiles( + iWifiManager.getWifiConfigsForPasspointProfiles( new ArrayList<>(results.keySet())); for (WifiConfiguration configuration : wifiConfigurations) { Map<Integer, List<ScanResult>> scanResultsPerNetworkType = results.get( @@ -1313,10 +1319,12 @@ public class WifiManager { public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders( @Nullable List<ScanResult> scanResults) { if (scanResults == null) { - return new HashMap<>(); + return Collections.emptyMap(); } try { - return getIWifiManager().getMatchingOsuProviders(scanResults); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return Collections.emptyMap(); + return iWifiManager.getMatchingOsuProviders(scanResults); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1343,7 +1351,9 @@ public class WifiManager { public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders( @NonNull Set<OsuProvider> osuProviders) { try { - return getIWifiManager().getMatchingPasspointConfigsForOsuProviders( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return Collections.emptyMap(); + return iWifiManager.getMatchingPasspointConfigsForOsuProviders( new ArrayList<>(osuProviders)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1428,7 +1438,9 @@ public class WifiManager { */ private int addOrUpdateNetwork(WifiConfiguration config) { try { - return getIWifiManager().addOrUpdateNetwork(config, mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return -1; + return iWifiManager.addOrUpdateNetwork(config, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1654,7 +1666,11 @@ public class WifiManager { Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper(); Binder binder = new Binder(); try { - getIWifiManager().registerNetworkRequestMatchCallback( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.registerNetworkRequestMatchCallback( binder, new NetworkRequestMatchCallbackProxy(looper, callback), callback.hashCode()); } catch (RemoteException e) { @@ -1680,7 +1696,11 @@ public class WifiManager { Log.v(TAG, "unregisterNetworkRequestMatchCallback: callback=" + callback); try { - getIWifiManager().unregisterNetworkRequestMatchCallback(callback.hashCode()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.unregisterNetworkRequestMatchCallback(callback.hashCode()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1714,7 +1734,9 @@ public class WifiManager { public @NetworkSuggestionsStatusCode int addNetworkSuggestions( @NonNull List<WifiNetworkSuggestion> networkSuggestions) { try { - return getIWifiManager().addNetworkSuggestions( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL; + return iWifiManager.addNetworkSuggestions( networkSuggestions, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1738,7 +1760,9 @@ public class WifiManager { public @NetworkSuggestionsStatusCode int removeNetworkSuggestions( @NonNull List<WifiNetworkSuggestion> networkSuggestions) { try { - return getIWifiManager().removeNetworkSuggestions( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL; + return iWifiManager.removeNetworkSuggestions( networkSuggestions, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1754,7 +1778,9 @@ public class WifiManager { @RequiresPermission(ACCESS_WIFI_STATE) public @NonNull List<WifiNetworkSuggestion> getNetworkSuggestions() { try { - return mService.getNetworkSuggestions(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return Collections.emptyList(); + return iWifiManager.getNetworkSuggestions(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -1784,7 +1810,11 @@ public class WifiManager { */ public void addOrUpdatePasspointConfiguration(PasspointConfiguration config) { try { - if (!getIWifiManager().addOrUpdatePasspointConfiguration( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + if (!iWifiManager.addOrUpdatePasspointConfiguration( config, mContext.getOpPackageName())) { throw new IllegalArgumentException(); } @@ -1808,7 +1838,11 @@ public class WifiManager { }) public void removePasspointConfiguration(String fqdn) { try { - if (!getIWifiManager().removePasspointConfiguration( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + if (!iWifiManager.removePasspointConfiguration( fqdn, mContext.getOpPackageName())) { throw new IllegalArgumentException(); } @@ -1832,7 +1866,9 @@ public class WifiManager { }) public List<PasspointConfiguration> getPasspointConfigurations() { try { - return getIWifiManager().getPasspointConfigurations(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) Collections.emptyList(); + return iWifiManager.getPasspointConfigurations(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1852,7 +1888,11 @@ public class WifiManager { */ public void queryPasspointIcon(long bssid, String fileName) { try { - getIWifiManager().queryPasspointIcon(bssid, fileName); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.queryPasspointIcon(bssid, fileName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1866,7 +1906,9 @@ public class WifiManager { */ public int matchProviderWithCurrentNetwork(String fqdn) { try { - return getIWifiManager().matchProviderWithCurrentNetwork(fqdn); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return -1; + return iWifiManager.matchProviderWithCurrentNetwork(fqdn); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1880,7 +1922,11 @@ public class WifiManager { */ public void deauthenticateNetwork(long holdoff, boolean ess) { try { - getIWifiManager().deauthenticateNetwork(holdoff, ess); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.deauthenticateNetwork(holdoff, ess); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1910,7 +1956,9 @@ public class WifiManager { @Deprecated public boolean removeNetwork(int netId) { try { - return getIWifiManager().removeNetwork(netId, mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.removeNetwork(netId, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1965,7 +2013,9 @@ public class WifiManager { boolean success; try { - success = getIWifiManager().enableNetwork( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + success = iWifiManager.enableNetwork( netId, attemptConnect, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -2002,7 +2052,9 @@ public class WifiManager { @Deprecated public boolean disableNetwork(int netId) { try { - return getIWifiManager().disableNetwork(netId, mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.disableNetwork(netId, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2025,7 +2077,9 @@ public class WifiManager { @Deprecated public boolean disconnect() { try { - return getIWifiManager().disconnect(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.disconnect(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2049,7 +2103,9 @@ public class WifiManager { @Deprecated public boolean reconnect() { try { - return getIWifiManager().reconnect(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.reconnect(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2073,7 +2129,9 @@ public class WifiManager { @Deprecated public boolean reassociate() { try { - return getIWifiManager().reassociate(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.reassociate(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2159,7 +2217,9 @@ public class WifiManager { private long getSupportedFeatures() { try { - return getIWifiManager().getSupportedFeatures(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return 0L; + return iWifiManager.getSupportedFeatures(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2289,8 +2349,10 @@ public class WifiManager { */ public WifiActivityEnergyInfo getControllerActivityEnergyInfo() { try { + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; synchronized(this) { - return getIWifiManager().reportActivityInfo(); + return iWifiManager.reportActivityInfo(); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -2329,8 +2391,10 @@ public class WifiManager { @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public boolean startScan(WorkSource workSource) { try { + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; String packageName = mContext.getOpPackageName(); - return getIWifiManager().startScan(packageName); + return iWifiManager.startScan(packageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2359,7 +2423,9 @@ public class WifiManager { */ public WifiInfo getConnectionInfo() { try { - return getIWifiManager().getConnectionInfo(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; + return iWifiManager.getConnectionInfo(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2373,7 +2439,9 @@ public class WifiManager { */ public List<ScanResult> getScanResults() { try { - return getIWifiManager().getScanResults(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return Collections.emptyList(); + return iWifiManager.getScanResults(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2392,7 +2460,9 @@ public class WifiManager { @Deprecated public boolean isScanAlwaysAvailable() { try { - return getIWifiManager().isScanAlwaysAvailable(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.isScanAlwaysAvailable(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2423,7 +2493,11 @@ public class WifiManager { */ public void setCountryCode(@NonNull String country) { try { - getIWifiManager().setCountryCode(country); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.setCountryCode(country); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2438,7 +2512,9 @@ public class WifiManager { @UnsupportedAppUsage public String getCountryCode() { try { - String country = getIWifiManager().getCountryCode(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; + String country = iWifiManager.getCountryCode(); return country; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -2453,7 +2529,9 @@ public class WifiManager { @UnsupportedAppUsage public boolean isDualBandSupported() { try { - return getIWifiManager().isDualBandSupported(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.isDualBandSupported(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2466,7 +2544,9 @@ public class WifiManager { */ public boolean isDualModeSupported() { try { - return getIWifiManager().needs5GHzToAnyApBandConversion(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.needs5GHzToAnyApBandConversion(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2479,7 +2559,9 @@ public class WifiManager { */ public DhcpInfo getDhcpInfo() { try { - return getIWifiManager().getDhcpInfo(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; + return iWifiManager.getDhcpInfo(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2506,7 +2588,9 @@ public class WifiManager { @Deprecated public boolean setWifiEnabled(boolean enabled) { try { - return getIWifiManager().setWifiEnabled(mContext.getOpPackageName(), enabled); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.setWifiEnabled(mContext.getOpPackageName(), enabled); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2521,7 +2605,9 @@ public class WifiManager { */ public int getWifiState() { try { - return getIWifiManager().getWifiEnabledState(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return WIFI_STATE_UNKNOWN; + return iWifiManager.getWifiEnabledState(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2595,7 +2681,11 @@ public class WifiManager { */ public void updateInterfaceIpState(String ifaceName, int mode) { try { - getIWifiManager().updateInterfaceIpState(ifaceName, mode); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.updateInterfaceIpState(ifaceName, mode); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2613,7 +2703,9 @@ public class WifiManager { */ public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) { try { - return getIWifiManager().startSoftAp(wifiConfig); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.startSoftAp(wifiConfig); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2628,7 +2720,9 @@ public class WifiManager { */ public boolean stopSoftAp() { try { - return getIWifiManager().stopSoftAp(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.stopSoftAp(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2696,8 +2790,12 @@ public class WifiManager { LocalOnlyHotspotCallbackProxy proxy = new LocalOnlyHotspotCallbackProxy(this, looper, callback); try { + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } String packageName = mContext.getOpPackageName(); - int returnCode = getIWifiManager().startLocalOnlyHotspot( + int returnCode = iWifiManager.startLocalOnlyHotspot( proxy.getMessenger(), new Binder(), packageName); if (returnCode != LocalOnlyHotspotCallback.REQUEST_REGISTERED) { // Send message to the proxy to make sure we call back on the correct thread @@ -2749,7 +2847,11 @@ public class WifiManager { } mLOHSCallbackProxy = null; try { - getIWifiManager().stopLocalOnlyHotspot(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.stopLocalOnlyHotspot(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2779,7 +2881,11 @@ public class WifiManager { Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper(); mLOHSObserverProxy = new LocalOnlyHotspotObserverProxy(this, looper, observer); try { - getIWifiManager().startWatchLocalOnlyHotspot( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.startWatchLocalOnlyHotspot( mLOHSObserverProxy.getMessenger(), new Binder()); mLOHSObserverProxy.registered(); } catch (RemoteException e) { @@ -2803,7 +2909,11 @@ public class WifiManager { } mLOHSObserverProxy = null; try { - getIWifiManager().stopWatchLocalOnlyHotspot(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.stopWatchLocalOnlyHotspot(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2823,7 +2933,9 @@ public class WifiManager { @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public int getWifiApState() { try { - return getIWifiManager().getWifiApEnabledState(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return WIFI_AP_STATE_FAILED; + return iWifiManager.getWifiApEnabledState(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2852,7 +2964,9 @@ public class WifiManager { @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public WifiConfiguration getWifiApConfiguration() { try { - return getIWifiManager().getWifiApConfiguration(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; + return iWifiManager.getWifiApConfiguration(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2869,7 +2983,9 @@ public class WifiManager { @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) { try { - return getIWifiManager().setWifiApConfiguration( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.setWifiApConfiguration( wifiConfig, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -2885,7 +3001,11 @@ public class WifiManager { public void notifyUserOfApBandConversion() { Log.d(TAG, "apBand was converted, notify the user"); try { - getIWifiManager().notifyUserOfApBandConversion(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.notifyUserOfApBandConversion(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2913,7 +3033,11 @@ public class WifiManager { */ public void setTdlsEnabled(InetAddress remoteIPAddress, boolean enable) { try { - getIWifiManager().enableTdls(remoteIPAddress.getHostAddress(), enable); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.enableTdls(remoteIPAddress.getHostAddress(), enable); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2927,7 +3051,11 @@ public class WifiManager { */ public void setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable) { try { - getIWifiManager().enableTdlsWithMacAddress(remoteMacAddress, enable); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.enableTdlsWithMacAddress(remoteMacAddress, enable); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3216,7 +3344,11 @@ public class WifiManager { Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper(); Binder binder = new Binder(); try { - getIWifiManager().registerSoftApCallback( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.registerSoftApCallback( binder, new SoftApCallbackProxy(looper, callback), callback.hashCode()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -3237,7 +3369,11 @@ public class WifiManager { Log.v(TAG, "unregisterSoftApCallback: callback=" + callback); try { - getIWifiManager().unregisterSoftApCallback(callback.hashCode()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.unregisterSoftApCallback(callback.hashCode()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3807,7 +3943,11 @@ public class WifiManager { public void disableEphemeralNetwork(String SSID) { if (SSID == null) throw new IllegalArgumentException("SSID cannot be null"); try { - getIWifiManager().disableEphemeralNetwork(SSID, mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.disableEphemeralNetwork(SSID, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3851,7 +3991,9 @@ public class WifiManager { @UnsupportedAppUsage private Messenger getWifiServiceMessenger() { try { - return getIWifiManager().getWifiServiceMessenger(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; + return iWifiManager.getWifiServiceMessenger(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3911,10 +4053,14 @@ public class WifiManager { synchronized (mBinder) { if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { try { - getIWifiManager().acquireWifiLock(mBinder, mLockType, mTag, mWorkSource); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.acquireWifiLock(mBinder, mLockType, mTag, mWorkSource); synchronized (WifiManager.this) { if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { - getIWifiManager().releaseWifiLock(mBinder); + iWifiManager.releaseWifiLock(mBinder); throw new UnsupportedOperationException( "Exceeded maximum number of wifi locks"); } @@ -3944,7 +4090,11 @@ public class WifiManager { synchronized (mBinder) { if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { try { - getIWifiManager().releaseWifiLock(mBinder); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.releaseWifiLock(mBinder); synchronized (WifiManager.this) { mActiveLockCount--; } @@ -4007,7 +4157,11 @@ public class WifiManager { } if (changed && mHeld) { try { - getIWifiManager().updateWifiLockWorkSource(mBinder, mWorkSource); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.updateWifiLockWorkSource(mBinder, mWorkSource); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4035,7 +4189,11 @@ public class WifiManager { synchronized (mBinder) { if (mHeld) { try { - getIWifiManager().releaseWifiLock(mBinder); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.releaseWifiLock(mBinder); synchronized (WifiManager.this) { mActiveLockCount--; } @@ -4148,10 +4306,14 @@ public class WifiManager { synchronized (mBinder) { if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { try { - getIWifiManager().acquireMulticastLock(mBinder, mTag); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.acquireMulticastLock(mBinder, mTag); synchronized (WifiManager.this) { if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { - getIWifiManager().releaseMulticastLock(mTag); + iWifiManager.releaseMulticastLock(mTag); throw new UnsupportedOperationException( "Exceeded maximum number of wifi locks"); } @@ -4193,7 +4355,11 @@ public class WifiManager { synchronized (mBinder) { if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { try { - getIWifiManager().releaseMulticastLock(mTag); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.releaseMulticastLock(mTag); synchronized (WifiManager.this) { mActiveLockCount--; } @@ -4270,7 +4436,9 @@ public class WifiManager { */ public boolean isMulticastEnabled() { try { - return getIWifiManager().isMulticastEnabled(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + return iWifiManager.isMulticastEnabled(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4283,7 +4451,9 @@ public class WifiManager { @UnsupportedAppUsage public boolean initializeMulticastFiltering() { try { - getIWifiManager().initializeMulticastFiltering(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return false; + iWifiManager.initializeMulticastFiltering(); return true; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -4308,7 +4478,11 @@ public class WifiManager { @UnsupportedAppUsage public void enableVerboseLogging (int verbose) { try { - getIWifiManager().enableVerboseLogging(verbose); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.enableVerboseLogging(verbose); } catch (Exception e) { //ignore any failure here Log.e(TAG, "enableVerboseLogging " + e.toString()); @@ -4323,7 +4497,9 @@ public class WifiManager { @UnsupportedAppUsage public int getVerboseLoggingLevel() { try { - return getIWifiManager().getVerboseLoggingLevel(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return -1; + return iWifiManager.getVerboseLoggingLevel(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4336,7 +4512,11 @@ public class WifiManager { */ public void factoryReset() { try { - getIWifiManager().factoryReset(mContext.getOpPackageName()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.factoryReset(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4350,7 +4530,9 @@ public class WifiManager { @UnsupportedAppUsage public Network getCurrentNetwork() { try { - return getIWifiManager().getCurrentNetwork(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; + return iWifiManager.getCurrentNetwork(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4382,7 +4564,11 @@ public class WifiManager { */ public void enableWifiConnectivityManager(boolean enabled) { try { - getIWifiManager().enableWifiConnectivityManager(enabled); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.enableWifiConnectivityManager(enabled); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4394,7 +4580,9 @@ public class WifiManager { */ public byte[] retrieveBackupData() { try { - return getIWifiManager().retrieveBackupData(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; + return iWifiManager.retrieveBackupData(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4406,7 +4594,11 @@ public class WifiManager { */ public void restoreBackupData(byte[] data) { try { - getIWifiManager().restoreBackupData(data); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.restoreBackupData(data); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4422,7 +4614,11 @@ public class WifiManager { @Deprecated public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) { try { - getIWifiManager().restoreSupplicantBackupData(supplicantData, ipConfigData); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.restoreSupplicantBackupData(supplicantData, ipConfigData); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4451,7 +4647,11 @@ public class WifiManager { throw new IllegalArgumentException("callback must not be null"); } try { - getIWifiManager().startSubscriptionProvisioning(provider, + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.startSubscriptionProvisioning(provider, new ProvisioningCallbackProxy(executor, callback)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -4565,7 +4765,11 @@ public class WifiManager { Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper(); Binder binder = new Binder(); try { - getIWifiManager().registerTrafficStateCallback( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.registerTrafficStateCallback( binder, new TrafficStateCallbackProxy(looper, callback), callback.hashCode()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -4585,7 +4789,11 @@ public class WifiManager { Log.v(TAG, "unregisterTrafficStateCallback: callback=" + callback); try { - getIWifiManager().unregisterTrafficStateCallback(callback.hashCode()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.unregisterTrafficStateCallback(callback.hashCode()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4641,7 +4849,9 @@ public class WifiManager { @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String[] getFactoryMacAddresses() { try { - return getIWifiManager().getFactoryMacAddresses(); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) return null; + return iWifiManager.getFactoryMacAddresses(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4710,7 +4920,11 @@ public class WifiManager { @RequiresPermission(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE) public void setDeviceMobilityState(@DeviceMobilityState int state) { try { - getIWifiManager().setDeviceMobilityState(state); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.setDeviceMobilityState(state); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4765,7 +4979,11 @@ public class WifiManager { @NonNull EasyConnectStatusCallback callback) { Binder binder = new Binder(); try { - getIWifiManager().startDppAsConfiguratorInitiator( + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.startDppAsConfiguratorInitiator( binder, enrolleeUri, selectedNetworkId, enrolleeNetworkRole, new EasyConnectCallbackProxy(executor, callback)); } catch (RemoteException e) { @@ -4792,7 +5010,11 @@ public class WifiManager { @NonNull EasyConnectStatusCallback callback) { Binder binder = new Binder(); try { - getIWifiManager().startDppAsEnrolleeInitiator(binder, configuratorUri, + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.startDppAsEnrolleeInitiator(binder, configuratorUri, new EasyConnectCallbackProxy(executor, callback)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -4813,8 +5035,12 @@ public class WifiManager { android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void stopEasyConnectSession() { try { + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } /* Request lower layers to stop/abort and clear resources */ - getIWifiManager().stopDppSession(); + iWifiManager.stopDppSession(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4913,7 +5139,11 @@ public class WifiManager { Log.v(TAG, "addOnWifiUsabilityStatsListener: listener=" + listener); } try { - getIWifiManager().addOnWifiUsabilityStatsListener(new Binder(), + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.addOnWifiUsabilityStatsListener(new Binder(), new IOnWifiUsabilityStatsListener.Stub() { @Override public void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq, @@ -4950,7 +5180,11 @@ public class WifiManager { Log.v(TAG, "removeOnWifiUsabilityStatsListener: listener=" + listener); } try { - getIWifiManager().removeOnWifiUsabilityStatsListener(listener.hashCode()); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.removeOnWifiUsabilityStatsListener(listener.hashCode()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4973,7 +5207,11 @@ public class WifiManager { @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec) { try { - getIWifiManager().updateWifiUsabilityScore(seqNum, score, predictionHorizonSec); + IWifiManager iWifiManager = getIWifiManager(); + if (iWifiManager == null) { + throw new RemoteException("Wifi service is not running"); + } + iWifiManager.updateWifiUsabilityScore(seqNum, score, predictionHorizonSec); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } |