diff options
318 files changed, 5457 insertions, 2771 deletions
diff --git a/Android.bp b/Android.bp index 0780f88df7c6..e756b3428164 100644 --- a/Android.bp +++ b/Android.bp @@ -1415,3 +1415,30 @@ filegroup { name: "framework-telephony-jarjar-rules", srcs: ["telephony/framework-telephony-jarjar-rules.txt"], } + +// protolog start +filegroup { + name: "protolog-common-src", + srcs: [ + "core/java/com/android/internal/protolog/common/**/*.java", + ], +} + +java_library { + name: "protolog-lib", + platform_apis: true, + srcs: [ + "core/java/com/android/internal/protolog/ProtoLogImpl.java", + "core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java", + ":protolog-common-src", + ], +} + +java_library { + name: "protolog-groups", + srcs: [ + "core/java/com/android/internal/protolog/ProtoLogGroup.java", + ":protolog-common-src", + ], +} +// protolog end diff --git a/StubLibraries.bp b/StubLibraries.bp index 0fe34fb650eb..2bd5aee0cd24 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -311,15 +311,6 @@ java_defaults { compile_dex: true, } -java_defaults { - name: "android_stubs_dists_default", - dist: { - targets: ["sdk", "win_sdk"], - tag: ".jar", - dest: "android.jar", - }, -} - java_library_static { name: "android_monolith_stubs_current", srcs: [ ":api-stubs-docs" ], @@ -355,21 +346,7 @@ java_library_static { name: "android_system_monolith_stubs_current", srcs: [ ":system-api-stubs-docs" ], static_libs: [ "private-stub-annotations-jar" ], - defaults: [ - "android_defaults_stubs_current", - "android_stubs_dists_default", - ], - dist: { - dir: "apistubs/android/system", - }, - dists: [ - { - // Legacy dist path - targets: ["sdk", "win_sdk"], - tag: ".jar", - dest: "android_system.jar", - }, - ], + defaults: ["android_defaults_stubs_current"], } java_library_static { @@ -401,34 +378,14 @@ java_library_static { name: "android_test_stubs_current", srcs: [ ":test-api-stubs-docs" ], static_libs: [ "private-stub-annotations-jar" ], - defaults: [ - "android_defaults_stubs_current", - "android_stubs_dists_default", - ], - dist: { - dir: "apistubs/android/test", - }, - dists: [ - { - // Legacy dist path - targets: ["sdk", "win_sdk"], - tag: ".jar", - dest: "android_test.jar", - }, - ], + defaults: ["android_defaults_stubs_current"], } java_library_static { name: "android_module_lib_stubs_current", srcs: [ ":module-lib-api-stubs-docs-non-updatable" ], - defaults: [ - "android_defaults_stubs_current", - "android_stubs_dists_default", - ], + defaults: ["android_defaults_stubs_current"], libs: ["sdk_system_29_android"], - dist: { - dir: "apistubs/android/module-lib", - }, } java_library_static { diff --git a/api/current.txt b/api/current.txt index b70103b931d4..69700f3b0a60 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5596,6 +5596,7 @@ package android.app { method public android.graphics.drawable.Icon getIcon(); method public android.app.RemoteInput[] getRemoteInputs(); method public int getSemanticAction(); + method public boolean isAuthenticationRequired(); method public boolean isContextual(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.Notification.Action> CREATOR; @@ -5625,6 +5626,7 @@ package android.app { method @NonNull public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Extender); method @NonNull public android.os.Bundle getExtras(); method @NonNull public android.app.Notification.Action.Builder setAllowGeneratedReplies(boolean); + method @NonNull public android.app.Notification.Action.Builder setAuthenticationRequired(boolean); method @NonNull public android.app.Notification.Action.Builder setContextual(boolean); method @NonNull public android.app.Notification.Action.Builder setSemanticAction(int); } @@ -24065,6 +24067,8 @@ package android.media { method public boolean isSink(); method public boolean isSource(); field public static final int TYPE_AUX_LINE = 19; // 0x13 + field public static final int TYPE_BLE_HEADSET = 26; // 0x1a + field public static final int TYPE_BLE_SPEAKER = 27; // 0x1b field public static final int TYPE_BLUETOOTH_A2DP = 8; // 0x8 field public static final int TYPE_BLUETOOTH_SCO = 7; // 0x7 field public static final int TYPE_BUILTIN_EARPIECE = 1; // 0x1 diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt index f53ac8c895ce..b587ea1f3b74 100644 --- a/api/module-lib-current.txt +++ b/api/module-lib-current.txt @@ -94,6 +94,7 @@ package android.os { } public interface Parcelable { + method public default int getStability(); field public static final int PARCELABLE_STABILITY_LOCAL = 0; // 0x0 field public static final int PARCELABLE_STABILITY_VINTF = 1; // 0x1 } diff --git a/api/system-current.txt b/api/system-current.txt index 94474277666d..b011e9af40a0 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -7141,6 +7141,8 @@ package android.net.wifi { field @Deprecated public static final int METERED_OVERRIDE_METERED = 1; // 0x1 field @Deprecated public static final int METERED_OVERRIDE_NONE = 0; // 0x0 field @Deprecated public static final int METERED_OVERRIDE_NOT_METERED = 2; // 0x2 + field @Deprecated public static final int RANDOMIZATION_AUTO = 3; // 0x3 + field @Deprecated public static final int RANDOMIZATION_ENHANCED = 2; // 0x2 field @Deprecated public static final int RANDOMIZATION_NONE = 0; // 0x0 field @Deprecated public static final int RANDOMIZATION_PERSISTENT = 1; // 0x1 field @Deprecated public static final int RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA = 17; // 0x11 diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp index a6c402ccc075..15e22a3410cf 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.cpp +++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp @@ -166,7 +166,7 @@ Status Idmap2Service::verifyIdmap(const std::string& target_apk_path, Status Idmap2Service::createIdmap(const std::string& target_apk_path, const std::string& overlay_apk_path, int32_t fulfilled_policies, bool enforce_overlayable, int32_t user_id ATTRIBUTE_UNUSED, - aidl::nullable<std::string>* _aidl_return) { + std::optional<std::string>* _aidl_return) { assert(_aidl_return); SYSTRACE << "Idmap2Service::createIdmap " << target_apk_path << " " << overlay_apk_path; _aidl_return->reset(); @@ -214,7 +214,7 @@ Status Idmap2Service::createIdmap(const std::string& target_apk_path, return error("failed to write to idmap path " + idmap_path); } - *_aidl_return = aidl::make_nullable<std::string>(idmap_path); + *_aidl_return = idmap_path; return ok(); } diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h index ea931c936b0e..1a445192aff8 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.h +++ b/cmds/idmap2/idmap2d/Idmap2Service.h @@ -21,7 +21,6 @@ #include <android-base/unique_fd.h> #include <binder/BinderService.h> -#include <binder/Nullable.h> #include "android/os/BnIdmap2.h" @@ -47,7 +46,7 @@ class Idmap2Service : public BinderService<Idmap2Service>, public BnIdmap2 { binder::Status createIdmap(const std::string& target_apk_path, const std::string& overlay_apk_path, int32_t fulfilled_policies, bool enforce_overlayable, int32_t user_id, - aidl::nullable<std::string>* _aidl_return) override; + std::optional<std::string>* _aidl_return) override; private: // Cache the crc of the android framework package since the crc cannot change without a reboot. diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp index 1579715727ac..7c419519a558 100644 --- a/cmds/statsd/Android.bp +++ b/cmds/statsd/Android.bp @@ -85,8 +85,9 @@ cc_defaults { "src/metrics/EventMetricProducer.cpp", "src/metrics/GaugeMetricProducer.cpp", "src/metrics/MetricProducer.cpp", - "src/metrics/metrics_manager_util.cpp", "src/metrics/MetricsManager.cpp", + "src/metrics/parsing_utils/config_update_utils.cpp", + "src/metrics/parsing_utils/metrics_manager_util.cpp", "src/metrics/ValueMetricProducer.cpp", "src/packages/UidMap.cpp", "src/shell/shell_config.proto", @@ -322,6 +323,8 @@ cc_test { "tests/metrics/metrics_test_helper.cpp", "tests/metrics/OringDurationTracker_test.cpp", "tests/metrics/ValueMetricProducer_test.cpp", + "tests/metrics/parsing_utils/config_update_utils_test.cpp", + "tests/metrics/parsing_utils/metrics_manager_util_test.cpp", "tests/MetricsManager_test.cpp", "tests/shell/ShellSubscriber_test.cpp", "tests/state/StateTracker_test.cpp", diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index 6327490b0b71..7bee4e2d1a36 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -546,7 +546,8 @@ void StatsLogProcessor::OnConfigUpdatedLocked(const int64_t timestampNs, const C } } else { // Preserve the existing MetricsManager, update necessary components and metadata in place. - configValid = it->second->updateConfig(timestampNs, config); + configValid = it->second->updateConfig(config, mTimeBaseNs, timestampNs, + mAnomalyAlarmMonitor, mPeriodicAlarmMonitor); if (configValid) { // TODO(b/162323476): refresh TTL, ensure init() is handled properly. mUidMap->OnConfigUpdated(key); diff --git a/cmds/statsd/src/hash.h b/cmds/statsd/src/hash.h index cfe869f60202..bd6b0cd47eaf 100644 --- a/cmds/statsd/src/hash.h +++ b/cmds/statsd/src/hash.h @@ -22,6 +22,7 @@ namespace android { namespace os { namespace statsd { +// Uses murmur2 hashing algorithm. extern uint32_t Hash32(const char *data, size_t n, uint32_t seed); extern uint64_t Hash64(const char* data, size_t n, uint64_t seed); diff --git a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp b/cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp index b94a9572113e..60bcc26f0873 100644 --- a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp +++ b/cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp @@ -27,8 +27,9 @@ using std::set; using std::unordered_map; using std::vector; -CombinationLogMatchingTracker::CombinationLogMatchingTracker(const int64_t& id, const int index) - : LogMatchingTracker(id, index) { +CombinationLogMatchingTracker::CombinationLogMatchingTracker(const int64_t& id, const int index, + const uint64_t protoHash) + : LogMatchingTracker(id, index, protoHash) { } CombinationLogMatchingTracker::~CombinationLogMatchingTracker() { diff --git a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.h b/cmds/statsd/src/matchers/CombinationLogMatchingTracker.h index 55bc46059fc1..6b8a7fb19cf0 100644 --- a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.h +++ b/cmds/statsd/src/matchers/CombinationLogMatchingTracker.h @@ -28,7 +28,7 @@ namespace statsd { // Represents a AtomMatcher_Combination in the StatsdConfig. class CombinationLogMatchingTracker : public virtual LogMatchingTracker { public: - CombinationLogMatchingTracker(const int64_t& id, const int index); + CombinationLogMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash); bool init(const std::vector<AtomMatcher>& allLogMatchers, const std::vector<sp<LogMatchingTracker>>& allTrackers, diff --git a/cmds/statsd/src/matchers/LogMatchingTracker.h b/cmds/statsd/src/matchers/LogMatchingTracker.h index 88ab4e6f683a..49a41add4560 100644 --- a/cmds/statsd/src/matchers/LogMatchingTracker.h +++ b/cmds/statsd/src/matchers/LogMatchingTracker.h @@ -33,8 +33,8 @@ namespace statsd { class LogMatchingTracker : public virtual RefBase { public: - LogMatchingTracker(const int64_t& id, const int index) - : mId(id), mIndex(index), mInitialized(false){}; + LogMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash) + : mId(id), mIndex(index), mInitialized(false), mProtoHash(protoHash){}; virtual ~LogMatchingTracker(){}; @@ -69,10 +69,14 @@ public: return mAtomIds; } - const int64_t& getId() const { + int64_t getId() const { return mId; } + uint64_t getProtoHash() const { + return mProtoHash; + } + protected: // Name of this matching. We don't really need the name, but it makes log message easy to debug. const int64_t mId; @@ -87,6 +91,14 @@ protected: // return kNotMatched when we receive an event with an id not in the list. This is especially // useful when we have a complex CombinationLogMatcherTracker. std::set<int> mAtomIds; + + // Hash of the AtomMatcher's proto bytes from StatsdConfig. + // Used to determine if the definition of this matcher has changed across a config update. + const uint64_t mProtoHash; + + FRIEND_TEST(MetricsManagerTest, TestCreateLogTrackerSimple); + FRIEND_TEST(MetricsManagerTest, TestCreateLogTrackerCombination); + FRIEND_TEST(ConfigUpdateTest, TestUpdateMatchers); }; } // namespace statsd diff --git a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp b/cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp index 082daf5a1916..ff47d35b36cc 100644 --- a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp +++ b/cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp @@ -26,11 +26,11 @@ namespace statsd { using std::unordered_map; using std::vector; - SimpleLogMatchingTracker::SimpleLogMatchingTracker(const int64_t& id, const int index, + const uint64_t protoHash, const SimpleAtomMatcher& matcher, - const UidMap& uidMap) - : LogMatchingTracker(id, index), mMatcher(matcher), mUidMap(uidMap) { + const sp<UidMap>& uidMap) + : LogMatchingTracker(id, index, protoHash), mMatcher(matcher), mUidMap(uidMap) { if (!matcher.has_atom_id()) { mInitialized = false; } else { diff --git a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.h b/cmds/statsd/src/matchers/SimpleLogMatchingTracker.h index a0f6a888bd44..e58e01252ade 100644 --- a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.h +++ b/cmds/statsd/src/matchers/SimpleLogMatchingTracker.h @@ -29,9 +29,8 @@ namespace statsd { class SimpleLogMatchingTracker : public virtual LogMatchingTracker { public: - SimpleLogMatchingTracker(const int64_t& id, const int index, - const SimpleAtomMatcher& matcher, - const UidMap& uidMap); + SimpleLogMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash, + const SimpleAtomMatcher& matcher, const sp<UidMap>& uidMap); ~SimpleLogMatchingTracker(); @@ -46,7 +45,7 @@ public: private: const SimpleAtomMatcher mMatcher; - const UidMap& mUidMap; + const sp<UidMap> mUidMap; }; } // namespace statsd diff --git a/cmds/statsd/src/matchers/matcher_util.cpp b/cmds/statsd/src/matchers/matcher_util.cpp index 2b4c6a3cbf1e..e6d91223308d 100644 --- a/cmds/statsd/src/matchers/matcher_util.cpp +++ b/cmds/statsd/src/matchers/matcher_util.cpp @@ -81,14 +81,15 @@ bool combinationMatch(const vector<int>& children, const LogicalOperation& opera return matched; } -bool tryMatchString(const UidMap& uidMap, const FieldValue& fieldValue, const string& str_match) { +bool tryMatchString(const sp<UidMap>& uidMap, const FieldValue& fieldValue, + const string& str_match) { if (isAttributionUidField(fieldValue) || isUidField(fieldValue)) { int uid = fieldValue.mValue.int_value; auto aidIt = UidMap::sAidToUidMapping.find(str_match); if (aidIt != UidMap::sAidToUidMapping.end()) { return ((int)aidIt->second) == uid; } - std::set<string> packageNames = uidMap.getAppNamesFromUid(uid, true /* normalize*/); + std::set<string> packageNames = uidMap->getAppNamesFromUid(uid, true /* normalize*/); return packageNames.find(str_match) != packageNames.end(); } else if (fieldValue.mValue.getType() == STRING) { return fieldValue.mValue.str_value == str_match; @@ -96,7 +97,7 @@ bool tryMatchString(const UidMap& uidMap, const FieldValue& fieldValue, const st return false; } -bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher, +bool matchesSimple(const sp<UidMap>& uidMap, const FieldValueMatcher& matcher, const vector<FieldValue>& values, int start, int end, int depth) { if (depth > 2) { ALOGE("Depth > 3 not supported"); @@ -353,7 +354,7 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher, } } -bool matchesSimple(const UidMap& uidMap, const SimpleAtomMatcher& simpleMatcher, +bool matchesSimple(const sp<UidMap>& uidMap, const SimpleAtomMatcher& simpleMatcher, const LogEvent& event) { if (event.GetTagId() != simpleMatcher.atom_id()) { return false; diff --git a/cmds/statsd/src/matchers/matcher_util.h b/cmds/statsd/src/matchers/matcher_util.h index 1ab3e87b5fed..130b6068bd19 100644 --- a/cmds/statsd/src/matchers/matcher_util.h +++ b/cmds/statsd/src/matchers/matcher_util.h @@ -36,8 +36,8 @@ enum MatchingState { bool combinationMatch(const std::vector<int>& children, const LogicalOperation& operation, const std::vector<MatchingState>& matcherResults); -bool matchesSimple(const UidMap& uidMap, - const SimpleAtomMatcher& simpleMatcher, const LogEvent& wrapper); +bool matchesSimple(const sp<UidMap>& uidMap, const SimpleAtomMatcher& simpleMatcher, + const LogEvent& wrapper); } // namespace statsd } // namespace os diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp index 189d8117ae55..2c3deca40fa0 100644 --- a/cmds/statsd/src/metrics/MetricsManager.cpp +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -26,7 +26,8 @@ #include "guardrail/StatsdStats.h" #include "matchers/CombinationLogMatchingTracker.h" #include "matchers/SimpleLogMatchingTracker.h" -#include "metrics_manager_util.h" +#include "parsing_utils/config_update_utils.h" +#include "parsing_utils/metrics_manager_util.h" #include "state/StateManager.h" #include "stats_log_util.h" #include "stats_util.h" @@ -76,13 +77,14 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config, // Init the ttl end timestamp. refreshTtl(timeBaseNs); - mConfigValid = initStatsdConfig( - key, config, *uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, - timeBaseNs, currentTimeNs, mTagIds, mAllAtomMatchers, mAllConditionTrackers, - mAllMetricProducers, mAllAnomalyTrackers, mAllPeriodicAlarmTrackers, - mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap, - mActivationAtomTrackerToMetricMap, mDeactivationAtomTrackerToMetricMap, - mAlertTrackerMap, mMetricIndexesWithActivation, mNoReportMetricIds); + mConfigValid = + initStatsdConfig(key, config, uidMap, pullerManager, anomalyAlarmMonitor, + periodicAlarmMonitor, timeBaseNs, currentTimeNs, mTagIds, + mAllAtomMatchers, mLogTrackerMap, mAllConditionTrackers, + mAllMetricProducers, mAllAnomalyTrackers, mAllPeriodicAlarmTrackers, + mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap, + mActivationAtomTrackerToMetricMap, mDeactivationAtomTrackerToMetricMap, + mAlertTrackerMap, mMetricIndexesWithActivation, mNoReportMetricIds); mHashStringsInReport = config.hash_strings_in_metric_report(); mVersionStringsInReport = config.version_strings_in_metric_report(); @@ -195,7 +197,19 @@ MetricsManager::~MetricsManager() { VLOG("~MetricsManager()"); } -bool MetricsManager::updateConfig(const int64_t currentTimeNs, const StatsdConfig& config) { +bool MetricsManager::updateConfig(const StatsdConfig& config, const int64_t timeBaseNs, + const int64_t currentTimeNs, + const sp<AlarmMonitor>& anomalyAlarmMonitor, + const sp<AlarmMonitor>& periodicAlarmMonitor) { + vector<sp<LogMatchingTracker>> newAtomMatchers; + unordered_map<int64_t, int> newLogTrackerMap; + mTagIds.clear(); + mConfigValid = + updateStatsdConfig(mConfigKey, config, mUidMap, mPullerManager, anomalyAlarmMonitor, + periodicAlarmMonitor, timeBaseNs, currentTimeNs, mAllAtomMatchers, + mLogTrackerMap, mTagIds, newAtomMatchers, newLogTrackerMap); + mAllAtomMatchers = newAtomMatchers; + mLogTrackerMap = newLogTrackerMap; return mConfigValid; } diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h index 042de29e173d..6f9a23362033 100644 --- a/cmds/statsd/src/metrics/MetricsManager.h +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -46,7 +46,9 @@ public: virtual ~MetricsManager(); - bool updateConfig(const int64_t currentTimeNs, const StatsdConfig& config); + bool updateConfig(const StatsdConfig& config, const int64_t timeBaseNs, + const int64_t currentTimeNs, const sp<AlarmMonitor>& anomalyAlarmMonitor, + const sp<AlarmMonitor>& periodicAlarmMonitor); // Return whether the configuration is valid. bool isConfigValid() const; @@ -237,6 +239,12 @@ private: // Hold all periodic alarm trackers. std::vector<sp<AlarmTracker>> mAllPeriodicAlarmTrackers; + // To make updating configs faster, we map the id of a LogMatchingTracker, MetricProducer, and + // ConditionTracker to its index in the corresponding vector. + + // Maps the id of an atom matcher to its index in mAllAtomMatchers. + std::unordered_map<int64_t, int> mLogTrackerMap; + // To make the log processing more efficient, we want to do as much filtering as possible // before we go into individual trackers and conditions to match. diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp new file mode 100644 index 000000000000..562e29124187 --- /dev/null +++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2020 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. + */ + +#define DEBUG false // STOPSHIP if true + +#include "config_update_utils.h" + +#include "external/StatsPullerManager.h" +#include "hash.h" +#include "metrics_manager_util.h" + +namespace android { +namespace os { +namespace statsd { + +// Recursive function to determine if a matcher needs to be updated. Populates matcherToUpdate. +// Returns whether the function was successful or not. +bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherIdx, + const unordered_map<int64_t, int>& oldLogTrackerMap, + const vector<sp<LogMatchingTracker>>& oldAtomMatchers, + const unordered_map<int64_t, int>& newLogTrackerMap, + vector<UpdateStatus>& matchersToUpdate, + vector<bool>& cycleTracker) { + // Have already examined this matcher. + if (matchersToUpdate[matcherIdx] != UPDATE_UNKNOWN) { + return true; + } + + const AtomMatcher& matcher = config.atom_matcher(matcherIdx); + int64_t id = matcher.id(); + // Check if new matcher. + const auto& oldLogTrackerIt = oldLogTrackerMap.find(id); + if (oldLogTrackerIt == oldLogTrackerMap.end()) { + matchersToUpdate[matcherIdx] = UPDATE_REPLACE; + return true; + } + + // This is an existing matcher. Check if it has changed. + string serializedMatcher; + if (!matcher.SerializeToString(&serializedMatcher)) { + ALOGE("Unable to serialize matcher %lld", (long long)id); + return false; + } + uint64_t newProtoHash = Hash64(serializedMatcher); + if (newProtoHash != oldAtomMatchers[oldLogTrackerIt->second]->getProtoHash()) { + matchersToUpdate[matcherIdx] = UPDATE_REPLACE; + return true; + } + + switch (matcher.contents_case()) { + case AtomMatcher::ContentsCase::kSimpleAtomMatcher: { + matchersToUpdate[matcherIdx] = UPDATE_PRESERVE; + return true; + } + case AtomMatcher::ContentsCase::kCombination: { + // Recurse to check if children have changed. + cycleTracker[matcherIdx] = true; + UpdateStatus status = UPDATE_PRESERVE; + for (const int64_t childMatcherId : matcher.combination().matcher()) { + const auto& childIt = newLogTrackerMap.find(childMatcherId); + if (childIt == newLogTrackerMap.end()) { + ALOGW("Matcher %lld not found in the config", (long long)childMatcherId); + return false; + } + const int childIdx = childIt->second; + if (cycleTracker[childIdx]) { + ALOGE("Cycle detected in matcher config"); + return false; + } + if (!determineMatcherUpdateStatus(config, childIdx, oldLogTrackerMap, + oldAtomMatchers, newLogTrackerMap, + matchersToUpdate, cycleTracker)) { + return false; + } + + if (matchersToUpdate[childIdx] == UPDATE_REPLACE) { + status = UPDATE_REPLACE; + break; + } + } + matchersToUpdate[matcherIdx] = status; + cycleTracker[matcherIdx] = false; + return true; + } + default: { + ALOGE("Matcher \"%lld\" malformed", (long long)id); + return false; + } + } + return true; +} + +bool updateLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap, + const unordered_map<int64_t, int>& oldLogTrackerMap, + const vector<sp<LogMatchingTracker>>& oldAtomMatchers, set<int>& allTagIds, + unordered_map<int64_t, int>& newLogTrackerMap, + vector<sp<LogMatchingTracker>>& newAtomMatchers) { + const int atomMatcherCount = config.atom_matcher_size(); + + vector<AtomMatcher> matcherProtos; + matcherProtos.reserve(atomMatcherCount); + newAtomMatchers.reserve(atomMatcherCount); + + // Maps matcher id to their position in the config. For fast lookup of dependencies. + for (int i = 0; i < atomMatcherCount; i++) { + const AtomMatcher& matcher = config.atom_matcher(i); + if (newLogTrackerMap.find(matcher.id()) != newLogTrackerMap.end()) { + ALOGE("Duplicate atom matcher found for id %lld", (long long)matcher.id()); + return false; + } + newLogTrackerMap[matcher.id()] = i; + matcherProtos.push_back(matcher); + } + + // For combination matchers, we need to determine if any children need to be updated. + vector<UpdateStatus> matchersToUpdate(atomMatcherCount, UPDATE_UNKNOWN); + vector<bool> cycleTracker(atomMatcherCount, false); + for (int i = 0; i < atomMatcherCount; i++) { + if (!determineMatcherUpdateStatus(config, i, oldLogTrackerMap, oldAtomMatchers, + newLogTrackerMap, matchersToUpdate, cycleTracker)) { + return false; + } + } + + for (int i = 0; i < atomMatcherCount; i++) { + const AtomMatcher& matcher = config.atom_matcher(i); + const int64_t id = matcher.id(); + switch (matchersToUpdate[i]) { + case UPDATE_PRESERVE: { + const auto& oldLogTrackerIt = oldLogTrackerMap.find(id); + if (oldLogTrackerIt == oldLogTrackerMap.end()) { + ALOGE("Could not find AtomMatcher %lld in the previous config, but expected it " + "to be there", + (long long)id); + return false; + } + const int oldIndex = oldLogTrackerIt->second; + newAtomMatchers.push_back(oldAtomMatchers[oldIndex]); + break; + } + case UPDATE_REPLACE: { + sp<LogMatchingTracker> tracker = createLogTracker(matcher, i, uidMap); + if (tracker == nullptr) { + return false; + } + newAtomMatchers.push_back(tracker); + break; + } + default: { + ALOGE("Matcher \"%lld\" update state is unknown. This should never happen", + (long long)id); + return false; + } + } + } + + std::fill(cycleTracker.begin(), cycleTracker.end(), false); + for (auto& matcher : newAtomMatchers) { + if (!matcher->init(matcherProtos, newAtomMatchers, newLogTrackerMap, cycleTracker)) { + return false; + } + // Collect all the tag ids that are interesting. TagIds exist in leaf nodes only. + const set<int>& tagIds = matcher->getAtomIds(); + allTagIds.insert(tagIds.begin(), tagIds.end()); + } + + return true; +} + +bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap, + const sp<StatsPullerManager>& pullerManager, + const sp<AlarmMonitor>& anomalyAlarmMonitor, + const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs, + const int64_t currentTimeNs, + const vector<sp<LogMatchingTracker>>& oldAtomMatchers, + const unordered_map<int64_t, int>& oldLogTrackerMap, set<int>& allTagIds, + vector<sp<LogMatchingTracker>>& newAtomMatchers, + unordered_map<int64_t, int>& newLogTrackerMap) { + if (!updateLogTrackers(config, uidMap, oldLogTrackerMap, oldAtomMatchers, allTagIds, + newLogTrackerMap, newAtomMatchers)) { + ALOGE("updateLogMatchingTrackers failed"); + return false; + } + + return true; +} + +} // namespace statsd +} // namespace os +} // namespace android
\ No newline at end of file diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h new file mode 100644 index 000000000000..951ab03cee47 --- /dev/null +++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include <vector> + +#include "anomaly/AlarmMonitor.h" +#include "external/StatsPullerManager.h" +#include "matchers/LogMatchingTracker.h" + +namespace android { +namespace os { +namespace statsd { + +// Helper functions for MetricsManager to update itself from a new StatsdConfig. +// *Note*: only updateStatsdConfig() should be called from outside this file. +// All other functions are intermediate steps, created to make unit testing easier. + +// Possible update states for a component. PRESERVE means we should keep the existing one. +// REPLACE means we should create a new one, either because it didn't exist or it changed. +enum UpdateStatus { + UPDATE_UNKNOWN = 0, + UPDATE_PRESERVE = 1, + UPDATE_REPLACE = 2, +}; + +// Recursive function to determine if a matcher needs to be updated. +// input: +// [config]: the input StatsdConfig +// [matcherIdx]: the index of the current matcher to be updated +// [newLogTrackerMap]: matcher id to index mapping in the input StatsdConfig +// [oldLogTrackerMap]: matcher id to index mapping in the existing MetricsManager +// [oldAtomMatchers]: stores the existing LogMatchingTrackers +// output: +// [matchersToUpdate]: vector of the update status of each matcher. The matcherIdx index will +// be updated from UPDATE_UNKNOWN after this call. +// [cycleTracker]: intermediate param used during recursion. +bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherIdx, + const unordered_map<int64_t, int>& oldLogTrackerMap, + const vector<sp<LogMatchingTracker>>& oldAtomMatchers, + const unordered_map<int64_t, int>& newLogTrackerMap, + vector<UpdateStatus>& matchersToUpdate, + vector<bool>& cycleTracker); + +// Updates the LogMatchingTrackers. +// input: +// [config]: the input StatsdConfig +// [oldLogTrackerMap]: existing matcher id to index mapping +// [oldAtomMatchers]: stores the existing LogMatchingTrackers +// output: +// [allTagIds]: contains the set of all interesting tag ids to this config. +// [newLogTrackerMap]: new matcher id to index mapping +// [newAtomMatchers]: stores the new LogMatchingTrackers +bool updateLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap, + const unordered_map<int64_t, int>& oldLogTrackerMap, + const vector<sp<LogMatchingTracker>>& oldAtomMatchers, set<int>& allTagIds, + unordered_map<int64_t, int>& newLogTrackerMap, + vector<sp<LogMatchingTracker>>& newAtomMatchers); + +// Updates the existing MetricsManager from a new StatsdConfig. +// Parameters are the members of MetricsManager. See MetricsManager for declaration. +bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap, + const sp<StatsPullerManager>& pullerManager, + const sp<AlarmMonitor>& anomalyAlarmMonitor, + const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs, + const int64_t currentTimeNs, + const std::vector<sp<LogMatchingTracker>>& oldAtomMatchers, + const unordered_map<int64_t, int>& oldLogTrackerMap, + std::set<int>& allTagIds, + std::vector<sp<LogMatchingTracker>>& newAtomMatchers, + unordered_map<int64_t, int>& newLogTrackerMap); + +} // namespace statsd +} // namespace os +} // namespace android
\ No newline at end of file diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp index 8917c36bb608..52ef95d19cdc 100644 --- a/cmds/statsd/src/metrics/metrics_manager_util.cpp +++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp @@ -22,10 +22,10 @@ #include <inttypes.h> #include "FieldValue.h" -#include "MetricProducer.h" #include "condition/CombinationConditionTracker.h" #include "condition/SimpleConditionTracker.h" #include "external/StatsPullerManager.h" +#include "hash.h" #include "matchers/CombinationLogMatchingTracker.h" #include "matchers/EventMatcherWizard.h" #include "matchers/SimpleLogMatchingTracker.h" @@ -33,6 +33,7 @@ #include "metrics/DurationMetricProducer.h" #include "metrics/EventMetricProducer.h" #include "metrics/GaugeMetricProducer.h" +#include "metrics/MetricProducer.h" #include "metrics/ValueMetricProducer.h" #include "state/StateManager.h" #include "stats_util.h" @@ -61,6 +62,28 @@ bool hasLeafNode(const FieldMatcher& matcher) { } // namespace +sp<LogMatchingTracker> createLogTracker(const AtomMatcher& logMatcher, const int index, + const sp<UidMap>& uidMap) { + string serializedMatcher; + if (!logMatcher.SerializeToString(&serializedMatcher)) { + ALOGE("Unable to serialize matcher %lld", (long long)logMatcher.id()); + return nullptr; + } + uint64_t protoHash = Hash64(serializedMatcher); + switch (logMatcher.contents_case()) { + case AtomMatcher::ContentsCase::kSimpleAtomMatcher: + return new SimpleLogMatchingTracker(logMatcher.id(), index, protoHash, + logMatcher.simple_atom_matcher(), uidMap); + break; + case AtomMatcher::ContentsCase::kCombination: + return new CombinationLogMatchingTracker(logMatcher.id(), index, protoHash); + break; + default: + ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id()); + return nullptr; + } +} + bool handleMetricWithLogTrackers(const int64_t what, const int metricIndex, const bool usedForDimension, const vector<sp<LogMatchingTracker>>& allAtomMatchers, @@ -184,9 +207,7 @@ bool handleMetricWithStateLink(const FieldMatcher& stateMatcher, // to provide the producer with state about its activators and deactivators. // Returns false if there are errors. bool handleMetricActivation( - const StatsdConfig& config, - const int64_t metricId, - const int metricIndex, + const StatsdConfig& config, const int64_t metricId, const int metricIndex, const unordered_map<int64_t, int>& metricToActivationMap, const unordered_map<int64_t, int>& logTrackerMap, unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap, @@ -210,10 +231,11 @@ bool handleMetricActivation( return false; } - ActivationType activationType = (activation.has_activation_type()) ? - activation.activation_type() : metricActivation.activation_type(); - std::shared_ptr<Activation> activationWrapper = std::make_shared<Activation>( - activationType, activation.ttl_seconds() * NS_PER_SEC); + ActivationType activationType = (activation.has_activation_type()) + ? activation.activation_type() + : metricActivation.activation_type(); + std::shared_ptr<Activation> activationWrapper = + std::make_shared<Activation>(activationType, activation.ttl_seconds() * NS_PER_SEC); int atomMatcherIndex = itr->second; activationAtomTrackerToMetricMap[atomMatcherIndex].push_back(metricIndex); @@ -235,7 +257,7 @@ bool handleMetricActivation( return true; } -bool initLogTrackers(const StatsdConfig& config, const UidMap& uidMap, +bool initLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap, unordered_map<int64_t, int>& logTrackerMap, vector<sp<LogMatchingTracker>>& allAtomMatchers, set<int>& allTagIds) { vector<AtomMatcher> matcherConfigs; @@ -245,22 +267,12 @@ bool initLogTrackers(const StatsdConfig& config, const UidMap& uidMap, for (int i = 0; i < atomMatcherCount; i++) { const AtomMatcher& logMatcher = config.atom_matcher(i); - int index = allAtomMatchers.size(); - switch (logMatcher.contents_case()) { - case AtomMatcher::ContentsCase::kSimpleAtomMatcher: - allAtomMatchers.push_back(new SimpleLogMatchingTracker( - logMatcher.id(), index, logMatcher.simple_atom_matcher(), uidMap)); - break; - case AtomMatcher::ContentsCase::kCombination: - allAtomMatchers.push_back( - new CombinationLogMatchingTracker(logMatcher.id(), index)); - break; - default: - ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id()); - return false; - // continue; + sp<LogMatchingTracker> tracker = createLogTracker(logMatcher, index, uidMap); + if (tracker == nullptr) { + return false; } + allAtomMatchers.push_back(tracker); if (logTrackerMap.find(logMatcher.id()) != logTrackerMap.end()) { ALOGE("Duplicate AtomMatcher found!"); return false; @@ -383,7 +395,7 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t const MetricActivation& metricActivation = config.metric_activation(i); int64_t metricId = metricActivation.metric_id(); if (metricToActivationMap.find(metricId) != metricToActivationMap.end()) { - ALOGE("Metric %lld has multiple MetricActivations", (long long) metricId); + ALOGE("Metric %lld has multiple MetricActivations", (long long)metricId); return false; } metricToActivationMap.insert({metricId, i}); @@ -402,9 +414,8 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t metricMap.insert({metric.id(), metricIndex}); int trackerIndex; if (!handleMetricWithLogTrackers(metric.what(), metricIndex, - metric.has_dimensions_in_what(), - allAtomMatchers, logTrackerMap, trackerToMetricMap, - trackerIndex)) { + metric.has_dimensions_in_what(), allAtomMatchers, + logTrackerMap, trackerToMetricMap, trackerIndex)) { return false; } @@ -438,10 +449,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t unordered_map<int, shared_ptr<Activation>> eventActivationMap; unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap; - bool success = handleMetricActivation(config, metric.id(), metricIndex, - metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap, - deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap, - eventDeactivationMap); + bool success = handleMetricActivation( + config, metric.id(), metricIndex, metricToActivationMap, logTrackerMap, + activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, + metricsWithActivation, eventActivationMap, eventDeactivationMap); if (!success) return false; sp<MetricProducer> countProducer = @@ -544,10 +555,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t unordered_map<int, shared_ptr<Activation>> eventActivationMap; unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap; - bool success = handleMetricActivation(config, metric.id(), metricIndex, - metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap, - deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap, - eventDeactivationMap); + bool success = handleMetricActivation( + config, metric.id(), metricIndex, metricToActivationMap, logTrackerMap, + activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, + metricsWithActivation, eventActivationMap, eventDeactivationMap); if (!success) return false; sp<MetricProducer> durationMetric = new DurationMetricProducer( @@ -591,10 +602,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t unordered_map<int, shared_ptr<Activation>> eventActivationMap; unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap; - bool success = handleMetricActivation(config, metric.id(), metricIndex, - metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap, - deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap, - eventDeactivationMap); + bool success = handleMetricActivation( + config, metric.id(), metricIndex, metricToActivationMap, logTrackerMap, + activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, + metricsWithActivation, eventActivationMap, eventDeactivationMap); if (!success) return false; sp<MetricProducer> eventMetric = @@ -626,9 +637,8 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t metricMap.insert({metric.id(), metricIndex}); int trackerIndex; if (!handleMetricWithLogTrackers(metric.what(), metricIndex, - metric.has_dimensions_in_what(), - allAtomMatchers, logTrackerMap, trackerToMetricMap, - trackerIndex)) { + metric.has_dimensions_in_what(), allAtomMatchers, + logTrackerMap, trackerToMetricMap, trackerIndex)) { return false; } @@ -718,9 +728,8 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t metricMap.insert({metric.id(), metricIndex}); int trackerIndex; if (!handleMetricWithLogTrackers(metric.what(), metricIndex, - metric.has_dimensions_in_what(), - allAtomMatchers, logTrackerMap, trackerToMetricMap, - trackerIndex)) { + metric.has_dimensions_in_what(), allAtomMatchers, + logTrackerMap, trackerToMetricMap, trackerIndex)) { return false; } @@ -775,10 +784,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t unordered_map<int, shared_ptr<Activation>> eventActivationMap; unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap; - bool success = handleMetricActivation(config, metric.id(), metricIndex, - metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap, - deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap, - eventDeactivationMap); + bool success = handleMetricActivation( + config, metric.id(), metricIndex, metricToActivationMap, logTrackerMap, + activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, + metricsWithActivation, eventActivationMap, eventDeactivationMap); if (!success) return false; sp<MetricProducer> gaugeProducer = new GaugeMetricProducer( @@ -813,8 +822,7 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t return true; } -bool initAlerts(const StatsdConfig& config, - const unordered_map<int64_t, int>& metricProducerMap, +bool initAlerts(const StatsdConfig& config, const unordered_map<int64_t, int>& metricProducerMap, unordered_map<int64_t, int>& alertTrackerMap, const sp<AlarmMonitor>& anomalyAlarmMonitor, vector<sp<MetricProducer>>& allMetricProducers, @@ -832,8 +840,8 @@ bool initAlerts(const StatsdConfig& config, return false; } if (alert.trigger_if_sum_gt() < 0 || alert.num_buckets() <= 0) { - ALOGW("invalid alert: threshold=%f num_buckets= %d", - alert.trigger_if_sum_gt(), alert.num_buckets()); + ALOGW("invalid alert: threshold=%f num_buckets= %d", alert.trigger_if_sum_gt(), + alert.num_buckets()); return false; } const int metricIndex = itr->second; @@ -853,14 +861,13 @@ bool initAlerts(const StatsdConfig& config, } if (subscription.subscriber_information_case() == Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) { - ALOGW("subscription \"%lld\" has no subscriber info.\"", - (long long)subscription.id()); + ALOGW("subscription \"%lld\" has no subscriber info.\"", (long long)subscription.id()); return false; } const auto& itr = alertTrackerMap.find(subscription.rule_id()); if (itr == alertTrackerMap.end()) { ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"", - (long long)subscription.id(), (long long)subscription.rule_id()); + (long long)subscription.id(), (long long)subscription.rule_id()); return false; } const int anomalyTrackerIndex = itr->second; @@ -870,12 +877,11 @@ bool initAlerts(const StatsdConfig& config, } bool initAlarms(const StatsdConfig& config, const ConfigKey& key, - const sp<AlarmMonitor>& periodicAlarmMonitor, - const int64_t timeBaseNs, const int64_t currentTimeNs, - vector<sp<AlarmTracker>>& allAlarmTrackers) { + const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs, + const int64_t currentTimeNs, vector<sp<AlarmTracker>>& allAlarmTrackers) { unordered_map<int64_t, int> alarmTrackerMap; int64_t startMillis = timeBaseNs / 1000 / 1000; - int64_t currentTimeMillis = currentTimeNs / 1000 /1000; + int64_t currentTimeMillis = currentTimeNs / 1000 / 1000; for (int i = 0; i < config.alarm_size(); i++) { const Alarm& alarm = config.alarm(i); if (alarm.offset_millis() <= 0) { @@ -888,8 +894,7 @@ bool initAlarms(const StatsdConfig& config, const ConfigKey& key, } alarmTrackerMap.insert(std::make_pair(alarm.id(), allAlarmTrackers.size())); allAlarmTrackers.push_back( - new AlarmTracker(startMillis, currentTimeMillis, - alarm, key, periodicAlarmMonitor)); + new AlarmTracker(startMillis, currentTimeMillis, alarm, key, periodicAlarmMonitor)); } for (int i = 0; i < config.subscription_size(); ++i) { const Subscription& subscription = config.subscription(i); @@ -898,14 +903,13 @@ bool initAlarms(const StatsdConfig& config, const ConfigKey& key, } if (subscription.subscriber_information_case() == Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) { - ALOGW("subscription \"%lld\" has no subscriber info.\"", - (long long)subscription.id()); + ALOGW("subscription \"%lld\" has no subscriber info.\"", (long long)subscription.id()); return false; } const auto& itr = alarmTrackerMap.find(subscription.rule_id()); if (itr == alarmTrackerMap.end()) { ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"", - (long long)subscription.id(), (long long)subscription.rule_id()); + (long long)subscription.id(), (long long)subscription.rule_id()); return false; } const int trackerIndex = itr->second; @@ -914,12 +918,13 @@ bool initAlarms(const StatsdConfig& config, const ConfigKey& key, return true; } -bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap, +bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap, const sp<StatsPullerManager>& pullerManager, const sp<AlarmMonitor>& anomalyAlarmMonitor, const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs, const int64_t currentTimeNs, set<int>& allTagIds, vector<sp<LogMatchingTracker>>& allAtomMatchers, + unordered_map<int64_t, int>& logTrackerMap, vector<sp<ConditionTracker>>& allConditionTrackers, vector<sp<MetricProducer>>& allMetricProducers, vector<sp<AnomalyTracker>>& allAnomalyTrackers, @@ -930,9 +935,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap, unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap, unordered_map<int64_t, int>& alertTrackerMap, - vector<int>& metricsWithActivation, - std::set<int64_t>& noReportMetricIds) { - unordered_map<int64_t, int> logTrackerMap; + vector<int>& metricsWithActivation, std::set<int64_t>& noReportMetricIds) { unordered_map<int64_t, int> conditionTrackerMap; vector<ConditionState> initialConditionCache; unordered_map<int64_t, int> metricProducerMap; @@ -969,8 +972,8 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& ALOGE("initAlerts failed"); return false; } - if (!initAlarms(config, key, periodicAlarmMonitor, - timeBaseNs, currentTimeNs, allPeriodicAlarmTrackers)) { + if (!initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs, + allPeriodicAlarmTrackers)) { ALOGE("initAlarms failed"); return false; } diff --git a/cmds/statsd/src/metrics/metrics_manager_util.h b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h index 96b5c26ff789..ed9951fd5ee6 100644 --- a/cmds/statsd/src/metrics/metrics_manager_util.h +++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h @@ -20,16 +20,28 @@ #include <unordered_map> #include <vector> -#include "../anomaly/AlarmTracker.h" -#include "../condition/ConditionTracker.h" -#include "../external/StatsPullerManager.h" -#include "../matchers/LogMatchingTracker.h" -#include "../metrics/MetricProducer.h" +#include "anomaly/AlarmTracker.h" +#include "condition/ConditionTracker.h" +#include "external/StatsPullerManager.h" +#include "matchers/LogMatchingTracker.h" +#include "metrics/MetricProducer.h" namespace android { namespace os { namespace statsd { +// Helper functions for creating individual config components from StatsdConfig. +// Should only be called from metrics_manager_util and config_update_utils. + +// Create a LogMatchingTracker. +// input: +// [logMatcher]: the input AtomMatcher from the StatsdConfig +// [index]: the index of the matcher +// output: +// new LogMatchingTracker, or null if the tracker is unable to be created +sp<LogMatchingTracker> createLogTracker(const AtomMatcher& logMatcher, const int index, + const sp<UidMap>& uidMap); + // Helper functions for MetricsManager to initialize from StatsdConfig. // *Note*: only initStatsdConfig() should be called from outside. // All other functions are intermediate @@ -44,8 +56,7 @@ namespace statsd { // [logTrackerMap]: this map should contain matcher name to index mapping // [allAtomMatchers]: should store the sp to all the LogMatchingTracker // [allTagIds]: contains the set of all interesting tag ids to this config. -bool initLogTrackers(const StatsdConfig& config, - const UidMap& uidMap, +bool initLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap, std::unordered_map<int64_t, int>& logTrackerMap, std::vector<sp<LogMatchingTracker>>& allAtomMatchers, std::set<int>& allTagIds); @@ -97,7 +108,7 @@ bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAt // [trackerToMetricMap]: contains the mapping from log tracker to MetricProducer index. bool initMetrics( const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs, - const int64_t currentTimeNs, UidMap& uidMap, const sp<StatsPullerManager>& pullerManager, + const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager, const std::unordered_map<int64_t, int>& logTrackerMap, const std::unordered_map<int64_t, int>& conditionTrackerMap, const std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks, @@ -116,12 +127,13 @@ bool initMetrics( // Initialize MetricsManager from StatsdConfig. // Parameters are the members of MetricsManager. See MetricsManager for declaration. -bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap, +bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap, const sp<StatsPullerManager>& pullerManager, const sp<AlarmMonitor>& anomalyAlarmMonitor, const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs, const int64_t currentTimeNs, std::set<int>& allTagIds, std::vector<sp<LogMatchingTracker>>& allAtomMatchers, + std::unordered_map<int64_t, int>& logTrackerMap, std::vector<sp<ConditionTracker>>& allConditionTrackers, std::vector<sp<MetricProducer>>& allMetricProducers, vector<sp<AnomalyTracker>>& allAnomalyTrackers, @@ -132,8 +144,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap, unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap, std::unordered_map<int64_t, int>& alertTrackerMap, - vector<int>& metricsWithActivation, - std::set<int64_t>& noReportMetricIds); + vector<int>& metricsWithActivation, std::set<int64_t>& noReportMetricIds); } // namespace statsd } // namespace os diff --git a/cmds/statsd/src/shell/ShellSubscriber.cpp b/cmds/statsd/src/shell/ShellSubscriber.cpp index fd883c29dba0..9d8f0c24e253 100644 --- a/cmds/statsd/src/shell/ShellSubscriber.cpp +++ b/cmds/statsd/src/shell/ShellSubscriber.cpp @@ -191,7 +191,7 @@ void ShellSubscriber::writePulledAtomsLocked(const vector<std::shared_ptr<LogEve mProto.clear(); int count = 0; for (const auto& event : data) { - if (matchesSimple(*mUidMap, matcher, *event)) { + if (matchesSimple(mUidMap, matcher, *event)) { count++; uint64_t atomToken = mProto.start(util::FIELD_TYPE_MESSAGE | util::FIELD_COUNT_REPEATED | FIELD_ID_ATOM); @@ -209,7 +209,7 @@ void ShellSubscriber::onLogEvent(const LogEvent& event) { mProto.clear(); for (const auto& matcher : mSubscriptionInfo->mPushedMatchers) { - if (matchesSimple(*mUidMap, matcher, event)) { + if (matchesSimple(mUidMap, matcher, event)) { uint64_t atomToken = mProto.start(util::FIELD_TYPE_MESSAGE | util::FIELD_COUNT_REPEATED | FIELD_ID_ATOM); event.ToProto(mProto); diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp index 6264c075426a..92cd04f37ee0 100644 --- a/cmds/statsd/tests/LogEntryMatcher_test.cpp +++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp @@ -110,7 +110,7 @@ void makeBoolLogEvent(LogEvent* logEvent, const int32_t atomId, const int64_t ti } // anonymous namespace TEST(AtomMatcherTest, TestSimpleMatcher) { - UidMap uidMap; + sp<UidMap> uidMap = new UidMap(); // Set up the matcher AtomMatcher matcher; @@ -129,7 +129,7 @@ TEST(AtomMatcherTest, TestSimpleMatcher) { } TEST(AtomMatcherTest, TestAttributionMatcher) { - UidMap uidMap; + sp<UidMap> uidMap = new UidMap(); std::vector<int> attributionUids = {1111, 2222, 3333}; std::vector<string> attributionTags = {"location1", "location2", "location3"}; @@ -204,7 +204,7 @@ TEST(AtomMatcherTest, TestAttributionMatcher) { "pkg0"); EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); - uidMap.updateMap( + uidMap->updateMap( 1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */, {android::String16("v1"), android::String16("v1"), android::String16("v2"), android::String16("v1"), android::String16("v2")}, @@ -356,8 +356,8 @@ TEST(AtomMatcherTest, TestAttributionMatcher) { } TEST(AtomMatcherTest, TestUidFieldMatcher) { - UidMap uidMap; - uidMap.updateMap( + sp<UidMap> uidMap = new UidMap(); + uidMap->updateMap( 1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */, {android::String16("v1"), android::String16("v1"), android::String16("v2"), android::String16("v1"), android::String16("v2")}, @@ -392,8 +392,8 @@ TEST(AtomMatcherTest, TestUidFieldMatcher) { } TEST(AtomMatcherTest, TestNeqAnyStringMatcher) { - UidMap uidMap; - uidMap.updateMap( + sp<UidMap> uidMap = new UidMap(); + uidMap->updateMap( 1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */, {android::String16("v1"), android::String16("v1"), android::String16("v2"), android::String16("v1"), android::String16("v2")}, @@ -453,8 +453,8 @@ TEST(AtomMatcherTest, TestNeqAnyStringMatcher) { } TEST(AtomMatcherTest, TestEqAnyStringMatcher) { - UidMap uidMap; - uidMap.updateMap( + sp<UidMap> uidMap = new UidMap(); + uidMap->updateMap( 1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */, {android::String16("v1"), android::String16("v1"), android::String16("v2"), android::String16("v1"), android::String16("v2")}, @@ -517,7 +517,7 @@ TEST(AtomMatcherTest, TestEqAnyStringMatcher) { } TEST(AtomMatcherTest, TestBoolMatcher) { - UidMap uidMap; + sp<UidMap> uidMap = new UidMap(); // Set up the matcher AtomMatcher matcher; auto simpleMatcher = matcher.mutable_simple_atom_matcher(); @@ -550,7 +550,7 @@ TEST(AtomMatcherTest, TestBoolMatcher) { } TEST(AtomMatcherTest, TestStringMatcher) { - UidMap uidMap; + sp<UidMap> uidMap = new UidMap(); // Set up the matcher AtomMatcher matcher; auto simpleMatcher = matcher.mutable_simple_atom_matcher(); @@ -568,7 +568,7 @@ TEST(AtomMatcherTest, TestStringMatcher) { } TEST(AtomMatcherTest, TestMultiFieldsMatcher) { - UidMap uidMap; + sp<UidMap> uidMap = new UidMap(); // Set up the matcher AtomMatcher matcher; auto simpleMatcher = matcher.mutable_simple_atom_matcher(); @@ -597,7 +597,7 @@ TEST(AtomMatcherTest, TestMultiFieldsMatcher) { } TEST(AtomMatcherTest, TestIntComparisonMatcher) { - UidMap uidMap; + sp<UidMap> uidMap = new UidMap(); // Set up the matcher AtomMatcher matcher; auto simpleMatcher = matcher.mutable_simple_atom_matcher(); @@ -654,7 +654,7 @@ TEST(AtomMatcherTest, TestIntComparisonMatcher) { } TEST(AtomMatcherTest, TestFloatComparisonMatcher) { - UidMap uidMap; + sp<UidMap> uidMap = new UidMap(); // Set up the matcher AtomMatcher matcher; auto simpleMatcher = matcher.mutable_simple_atom_matcher(); diff --git a/cmds/statsd/tests/MetricsManager_test.cpp b/cmds/statsd/tests/MetricsManager_test.cpp index 6259757fe092..8dd608347064 100644 --- a/cmds/statsd/tests/MetricsManager_test.cpp +++ b/cmds/statsd/tests/MetricsManager_test.cpp @@ -28,7 +28,7 @@ #include "src/metrics/GaugeMetricProducer.h" #include "src/metrics/MetricProducer.h" #include "src/metrics/ValueMetricProducer.h" -#include "src/metrics/metrics_manager_util.h" +#include "src/metrics/parsing_utils/metrics_manager_util.h" #include "src/state/StateManager.h" #include "statsd_test_util.h" @@ -48,7 +48,6 @@ namespace statsd { namespace { const ConfigKey kConfigKey(0, 12345); -const long kAlertId = 3; const long timeBaseSec = 1000; @@ -90,287 +89,6 @@ StatsdConfig buildGoodConfig() { metric->set_bucket(ONE_MINUTE); metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/); metric->mutable_dimensions_in_what()->add_child()->set_field(1); - - config.add_no_report_metric(3); - - auto alert = config.add_alert(); - alert->set_id(kAlertId); - alert->set_metric_id(3); - alert->set_num_buckets(10); - alert->set_refractory_period_secs(100); - alert->set_trigger_if_sum_gt(100); - return config; -} - -StatsdConfig buildCircleMatchers() { - StatsdConfig config; - config.set_id(12345); - - AtomMatcher* eventMatcher = config.add_atom_matcher(); - eventMatcher->set_id(StringToId("SCREEN_IS_ON")); - - SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); - simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); - simpleAtomMatcher->add_field_value_matcher()->set_field( - 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); - simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( - 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/); - - eventMatcher = config.add_atom_matcher(); - eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF")); - - AtomMatcher_Combination* combination = eventMatcher->mutable_combination(); - combination->set_operation(LogicalOperation::OR); - combination->add_matcher(StringToId("SCREEN_IS_ON")); - // Circle dependency - combination->add_matcher(StringToId("SCREEN_ON_OR_OFF")); - - return config; -} - -StatsdConfig buildAlertWithUnknownMetric() { - StatsdConfig config; - config.set_id(12345); - - AtomMatcher* eventMatcher = config.add_atom_matcher(); - eventMatcher->set_id(StringToId("SCREEN_IS_ON")); - - CountMetric* metric = config.add_count_metric(); - metric->set_id(3); - metric->set_what(StringToId("SCREEN_IS_ON")); - metric->set_bucket(ONE_MINUTE); - metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/); - metric->mutable_dimensions_in_what()->add_child()->set_field(1); - - auto alert = config.add_alert(); - alert->set_id(3); - alert->set_metric_id(2); - alert->set_num_buckets(10); - alert->set_refractory_period_secs(100); - alert->set_trigger_if_sum_gt(100); - return config; -} - -StatsdConfig buildMissingMatchers() { - StatsdConfig config; - config.set_id(12345); - - AtomMatcher* eventMatcher = config.add_atom_matcher(); - eventMatcher->set_id(StringToId("SCREEN_IS_ON")); - - SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); - simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); - simpleAtomMatcher->add_field_value_matcher()->set_field( - 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); - simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( - 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/); - - eventMatcher = config.add_atom_matcher(); - eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF")); - - AtomMatcher_Combination* combination = eventMatcher->mutable_combination(); - combination->set_operation(LogicalOperation::OR); - combination->add_matcher(StringToId("SCREEN_IS_ON")); - // undefined matcher - combination->add_matcher(StringToId("ABC")); - - return config; -} - -StatsdConfig buildMissingPredicate() { - StatsdConfig config; - config.set_id(12345); - - CountMetric* metric = config.add_count_metric(); - metric->set_id(3); - metric->set_what(StringToId("SCREEN_EVENT")); - metric->set_bucket(ONE_MINUTE); - metric->set_condition(StringToId("SOME_CONDITION")); - - AtomMatcher* eventMatcher = config.add_atom_matcher(); - eventMatcher->set_id(StringToId("SCREEN_EVENT")); - - SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); - simpleAtomMatcher->set_atom_id(2); - - return config; -} - -StatsdConfig buildDimensionMetricsWithMultiTags() { - StatsdConfig config; - config.set_id(12345); - - AtomMatcher* eventMatcher = config.add_atom_matcher(); - eventMatcher->set_id(StringToId("BATTERY_VERY_LOW")); - SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); - simpleAtomMatcher->set_atom_id(2); - - eventMatcher = config.add_atom_matcher(); - eventMatcher->set_id(StringToId("BATTERY_VERY_VERY_LOW")); - simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); - simpleAtomMatcher->set_atom_id(3); - - eventMatcher = config.add_atom_matcher(); - eventMatcher->set_id(StringToId("BATTERY_LOW")); - - AtomMatcher_Combination* combination = eventMatcher->mutable_combination(); - combination->set_operation(LogicalOperation::OR); - combination->add_matcher(StringToId("BATTERY_VERY_LOW")); - combination->add_matcher(StringToId("BATTERY_VERY_VERY_LOW")); - - // Count process state changes, slice by uid, while SCREEN_IS_OFF - CountMetric* metric = config.add_count_metric(); - metric->set_id(3); - metric->set_what(StringToId("BATTERY_LOW")); - metric->set_bucket(ONE_MINUTE); - // This case is interesting. We want to dimension across two atoms. - metric->mutable_dimensions_in_what()->add_child()->set_field(1); - - auto alert = config.add_alert(); - alert->set_id(kAlertId); - alert->set_metric_id(3); - alert->set_num_buckets(10); - alert->set_refractory_period_secs(100); - alert->set_trigger_if_sum_gt(100); - return config; -} - -StatsdConfig buildCirclePredicates() { - StatsdConfig config; - config.set_id(12345); - - AtomMatcher* eventMatcher = config.add_atom_matcher(); - eventMatcher->set_id(StringToId("SCREEN_IS_ON")); - - SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); - simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); - simpleAtomMatcher->add_field_value_matcher()->set_field( - 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); - simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( - 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/); - - eventMatcher = config.add_atom_matcher(); - eventMatcher->set_id(StringToId("SCREEN_IS_OFF")); - - simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); - simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); - simpleAtomMatcher->add_field_value_matcher()->set_field( - 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); - simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( - 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/); - - auto condition = config.add_predicate(); - condition->set_id(StringToId("SCREEN_IS_ON")); - SimplePredicate* simplePredicate = condition->mutable_simple_predicate(); - simplePredicate->set_start(StringToId("SCREEN_IS_ON")); - simplePredicate->set_stop(StringToId("SCREEN_IS_OFF")); - - condition = config.add_predicate(); - condition->set_id(StringToId("SCREEN_IS_EITHER_ON_OFF")); - - Predicate_Combination* combination = condition->mutable_combination(); - combination->set_operation(LogicalOperation::OR); - combination->add_predicate(StringToId("SCREEN_IS_ON")); - combination->add_predicate(StringToId("SCREEN_IS_EITHER_ON_OFF")); - - return config; -} - -StatsdConfig buildConfigWithDifferentPredicates() { - StatsdConfig config; - config.set_id(12345); - - auto pulledAtomMatcher = - CreateSimpleAtomMatcher("SUBSYSTEM_SLEEP", util::SUBSYSTEM_SLEEP_STATE); - *config.add_atom_matcher() = pulledAtomMatcher; - auto screenOnAtomMatcher = CreateScreenTurnedOnAtomMatcher(); - *config.add_atom_matcher() = screenOnAtomMatcher; - auto screenOffAtomMatcher = CreateScreenTurnedOffAtomMatcher(); - *config.add_atom_matcher() = screenOffAtomMatcher; - auto batteryNoneAtomMatcher = CreateBatteryStateNoneMatcher(); - *config.add_atom_matcher() = batteryNoneAtomMatcher; - auto batteryUsbAtomMatcher = CreateBatteryStateUsbMatcher(); - *config.add_atom_matcher() = batteryUsbAtomMatcher; - - // Simple condition with InitialValue set to default (unknown). - auto screenOnUnknownPredicate = CreateScreenIsOnPredicate(); - *config.add_predicate() = screenOnUnknownPredicate; - - // Simple condition with InitialValue set to false. - auto screenOnFalsePredicate = config.add_predicate(); - screenOnFalsePredicate->set_id(StringToId("ScreenIsOnInitialFalse")); - SimplePredicate* simpleScreenOnFalsePredicate = - screenOnFalsePredicate->mutable_simple_predicate(); - simpleScreenOnFalsePredicate->set_start(screenOnAtomMatcher.id()); - simpleScreenOnFalsePredicate->set_stop(screenOffAtomMatcher.id()); - simpleScreenOnFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE); - - // Simple condition with InitialValue set to false. - auto onBatteryFalsePredicate = config.add_predicate(); - onBatteryFalsePredicate->set_id(StringToId("OnBatteryInitialFalse")); - SimplePredicate* simpleOnBatteryFalsePredicate = - onBatteryFalsePredicate->mutable_simple_predicate(); - simpleOnBatteryFalsePredicate->set_start(batteryNoneAtomMatcher.id()); - simpleOnBatteryFalsePredicate->set_stop(batteryUsbAtomMatcher.id()); - simpleOnBatteryFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE); - - // Combination condition with both simple condition InitialValues set to false. - auto screenOnFalseOnBatteryFalsePredicate = config.add_predicate(); - screenOnFalseOnBatteryFalsePredicate->set_id(StringToId("ScreenOnFalseOnBatteryFalse")); - screenOnFalseOnBatteryFalsePredicate->mutable_combination()->set_operation( - LogicalOperation::AND); - addPredicateToPredicateCombination(*screenOnFalsePredicate, - screenOnFalseOnBatteryFalsePredicate); - addPredicateToPredicateCombination(*onBatteryFalsePredicate, - screenOnFalseOnBatteryFalsePredicate); - - // Combination condition with one simple condition InitialValue set to unknown and one set to - // false. - auto screenOnUnknownOnBatteryFalsePredicate = config.add_predicate(); - screenOnUnknownOnBatteryFalsePredicate->set_id(StringToId("ScreenOnUnknowneOnBatteryFalse")); - screenOnUnknownOnBatteryFalsePredicate->mutable_combination()->set_operation( - LogicalOperation::AND); - addPredicateToPredicateCombination(screenOnUnknownPredicate, - screenOnUnknownOnBatteryFalsePredicate); - addPredicateToPredicateCombination(*onBatteryFalsePredicate, - screenOnUnknownOnBatteryFalsePredicate); - - // Simple condition metric with initial value false. - ValueMetric* metric1 = config.add_value_metric(); - metric1->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialFalse")); - metric1->set_what(pulledAtomMatcher.id()); - *metric1->mutable_value_field() = - CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); - metric1->set_bucket(FIVE_MINUTES); - metric1->set_condition(screenOnFalsePredicate->id()); - - // Simple condition metric with initial value unknown. - ValueMetric* metric2 = config.add_value_metric(); - metric2->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialUnknown")); - metric2->set_what(pulledAtomMatcher.id()); - *metric2->mutable_value_field() = - CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); - metric2->set_bucket(FIVE_MINUTES); - metric2->set_condition(screenOnUnknownPredicate.id()); - - // Combination condition metric with initial values false and false. - ValueMetric* metric3 = config.add_value_metric(); - metric3->set_id(StringToId("ValueSubsystemSleepWhileScreenOnFalseDeviceUnpluggedFalse")); - metric3->set_what(pulledAtomMatcher.id()); - *metric3->mutable_value_field() = - CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); - metric3->set_bucket(FIVE_MINUTES); - metric3->set_condition(screenOnFalseOnBatteryFalsePredicate->id()); - - // Combination condition metric with initial values unknown and false. - ValueMetric* metric4 = config.add_value_metric(); - metric4->set_id(StringToId("ValueSubsystemSleepWhileScreenOnUnknownDeviceUnpluggedFalse")); - metric4->set_what(pulledAtomMatcher.id()); - *metric4->mutable_value_field() = - CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); - metric4->set_bucket(FIVE_MINUTES); - metric4->set_condition(screenOnUnknownOnBatteryFalsePredicate->id()); - return config; } @@ -379,274 +97,6 @@ bool isSubset(const set<int32_t>& set1, const set<int32_t>& set2) { } } // anonymous namespace -TEST(MetricsManagerTest, TestInitialConditions) { - UidMap uidMap; - sp<StatsPullerManager> pullerManager = new StatsPullerManager(); - sp<AlarmMonitor> anomalyAlarmMonitor; - sp<AlarmMonitor> periodicAlarmMonitor; - StatsdConfig config = buildConfigWithDifferentPredicates(); - set<int> allTagIds; - vector<sp<LogMatchingTracker>> allAtomMatchers; - vector<sp<ConditionTracker>> allConditionTrackers; - vector<sp<MetricProducer>> allMetricProducers; - std::vector<sp<AnomalyTracker>> allAnomalyTrackers; - std::vector<sp<AlarmTracker>> allAlarmTrackers; - unordered_map<int, std::vector<int>> conditionToMetricMap; - unordered_map<int, std::vector<int>> trackerToMetricMap; - unordered_map<int, std::vector<int>> trackerToConditionMap; - unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; - unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; - unordered_map<int64_t, int> alertTrackerMap; - vector<int> metricsWithActivation; - std::set<int64_t> noReportMetricIds; - - EXPECT_TRUE(initStatsdConfig( - kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, - timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, allConditionTrackers, - allMetricProducers, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, - trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap, - deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation, - noReportMetricIds)); - ASSERT_EQ(4u, allMetricProducers.size()); - ASSERT_EQ(5u, allConditionTrackers.size()); - - ConditionKey queryKey; - vector<ConditionState> conditionCache(5, ConditionState::kNotEvaluated); - - allConditionTrackers[3]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache); - allConditionTrackers[4]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache); - EXPECT_EQ(ConditionState::kUnknown, conditionCache[0]); - EXPECT_EQ(ConditionState::kFalse, conditionCache[1]); - EXPECT_EQ(ConditionState::kFalse, conditionCache[2]); - EXPECT_EQ(ConditionState::kFalse, conditionCache[3]); - EXPECT_EQ(ConditionState::kUnknown, conditionCache[4]); - - EXPECT_EQ(ConditionState::kFalse, allMetricProducers[0]->mCondition); - EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[1]->mCondition); - EXPECT_EQ(ConditionState::kFalse, allMetricProducers[2]->mCondition); - EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[3]->mCondition); -} - -TEST(MetricsManagerTest, TestGoodConfig) { - UidMap uidMap; - sp<StatsPullerManager> pullerManager = new StatsPullerManager(); - sp<AlarmMonitor> anomalyAlarmMonitor; - sp<AlarmMonitor> periodicAlarmMonitor; - StatsdConfig config = buildGoodConfig(); - set<int> allTagIds; - vector<sp<LogMatchingTracker>> allAtomMatchers; - vector<sp<ConditionTracker>> allConditionTrackers; - vector<sp<MetricProducer>> allMetricProducers; - std::vector<sp<AnomalyTracker>> allAnomalyTrackers; - std::vector<sp<AlarmTracker>> allAlarmTrackers; - unordered_map<int, std::vector<int>> conditionToMetricMap; - unordered_map<int, std::vector<int>> trackerToMetricMap; - unordered_map<int, std::vector<int>> trackerToConditionMap; - unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; - unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; - unordered_map<int64_t, int> alertTrackerMap; - vector<int> metricsWithActivation; - std::set<int64_t> noReportMetricIds; - - EXPECT_TRUE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, - periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds, - allAtomMatchers, allConditionTrackers, allMetricProducers, - allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, - trackerToMetricMap, trackerToConditionMap, - activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, - alertTrackerMap, metricsWithActivation, - noReportMetricIds)); - ASSERT_EQ(1u, allMetricProducers.size()); - ASSERT_EQ(1u, allAnomalyTrackers.size()); - ASSERT_EQ(1u, noReportMetricIds.size()); - ASSERT_EQ(1u, alertTrackerMap.size()); - EXPECT_NE(alertTrackerMap.find(kAlertId), alertTrackerMap.end()); - EXPECT_EQ(alertTrackerMap.find(kAlertId)->second, 0); -} - -TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) { - UidMap uidMap; - sp<StatsPullerManager> pullerManager = new StatsPullerManager(); - sp<AlarmMonitor> anomalyAlarmMonitor; - sp<AlarmMonitor> periodicAlarmMonitor; - StatsdConfig config = buildDimensionMetricsWithMultiTags(); - set<int> allTagIds; - vector<sp<LogMatchingTracker>> allAtomMatchers; - vector<sp<ConditionTracker>> allConditionTrackers; - vector<sp<MetricProducer>> allMetricProducers; - std::vector<sp<AnomalyTracker>> allAnomalyTrackers; - std::vector<sp<AlarmTracker>> allAlarmTrackers; - unordered_map<int, std::vector<int>> conditionToMetricMap; - unordered_map<int, std::vector<int>> trackerToMetricMap; - unordered_map<int, std::vector<int>> trackerToConditionMap; - unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; - unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; - unordered_map<int64_t, int> alertTrackerMap; - vector<int> metricsWithActivation; - std::set<int64_t> noReportMetricIds; - - EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, - periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds, - allAtomMatchers, allConditionTrackers, allMetricProducers, - allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, - trackerToMetricMap, trackerToConditionMap, - activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, - alertTrackerMap, metricsWithActivation, - noReportMetricIds)); -} - -TEST(MetricsManagerTest, TestCircleLogMatcherDependency) { - UidMap uidMap; - sp<StatsPullerManager> pullerManager = new StatsPullerManager(); - sp<AlarmMonitor> anomalyAlarmMonitor; - sp<AlarmMonitor> periodicAlarmMonitor; - StatsdConfig config = buildCircleMatchers(); - set<int> allTagIds; - vector<sp<LogMatchingTracker>> allAtomMatchers; - vector<sp<ConditionTracker>> allConditionTrackers; - vector<sp<MetricProducer>> allMetricProducers; - std::vector<sp<AnomalyTracker>> allAnomalyTrackers; - std::vector<sp<AlarmTracker>> allAlarmTrackers; - unordered_map<int, std::vector<int>> conditionToMetricMap; - unordered_map<int, std::vector<int>> trackerToMetricMap; - unordered_map<int, std::vector<int>> trackerToConditionMap; - unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; - unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; - unordered_map<int64_t, int> alertTrackerMap; - vector<int> metricsWithActivation; - std::set<int64_t> noReportMetricIds; - - EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, - periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds, - allAtomMatchers, allConditionTrackers, allMetricProducers, - allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, - trackerToMetricMap, trackerToConditionMap, - activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, - alertTrackerMap, metricsWithActivation, - noReportMetricIds)); -} - -TEST(MetricsManagerTest, TestMissingMatchers) { - UidMap uidMap; - sp<StatsPullerManager> pullerManager = new StatsPullerManager(); - sp<AlarmMonitor> anomalyAlarmMonitor; - sp<AlarmMonitor> periodicAlarmMonitor; - StatsdConfig config = buildMissingMatchers(); - set<int> allTagIds; - vector<sp<LogMatchingTracker>> allAtomMatchers; - vector<sp<ConditionTracker>> allConditionTrackers; - vector<sp<MetricProducer>> allMetricProducers; - std::vector<sp<AnomalyTracker>> allAnomalyTrackers; - std::vector<sp<AlarmTracker>> allAlarmTrackers; - unordered_map<int, std::vector<int>> conditionToMetricMap; - unordered_map<int, std::vector<int>> trackerToMetricMap; - unordered_map<int, std::vector<int>> trackerToConditionMap; - unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; - unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; - unordered_map<int64_t, int> alertTrackerMap; - vector<int> metricsWithActivation; - std::set<int64_t> noReportMetricIds; - EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, - periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds, - allAtomMatchers, allConditionTrackers, allMetricProducers, - allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, - trackerToMetricMap, trackerToConditionMap, - activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, - alertTrackerMap, metricsWithActivation, - noReportMetricIds)); -} - -TEST(MetricsManagerTest, TestMissingPredicate) { - UidMap uidMap; - sp<StatsPullerManager> pullerManager = new StatsPullerManager(); - sp<AlarmMonitor> anomalyAlarmMonitor; - sp<AlarmMonitor> periodicAlarmMonitor; - StatsdConfig config = buildMissingPredicate(); - set<int> allTagIds; - vector<sp<LogMatchingTracker>> allAtomMatchers; - vector<sp<ConditionTracker>> allConditionTrackers; - vector<sp<MetricProducer>> allMetricProducers; - std::vector<sp<AnomalyTracker>> allAnomalyTrackers; - std::vector<sp<AlarmTracker>> allAlarmTrackers; - unordered_map<int, std::vector<int>> conditionToMetricMap; - unordered_map<int, std::vector<int>> trackerToMetricMap; - unordered_map<int, std::vector<int>> trackerToConditionMap; - unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; - unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; - unordered_map<int64_t, int> alertTrackerMap; - vector<int> metricsWithActivation; - std::set<int64_t> noReportMetricIds; - EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, - periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds, - allAtomMatchers, allConditionTrackers, allMetricProducers, - allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, - trackerToMetricMap, trackerToConditionMap, - activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, - alertTrackerMap, metricsWithActivation, noReportMetricIds)); -} - -TEST(MetricsManagerTest, TestCirclePredicateDependency) { - UidMap uidMap; - sp<StatsPullerManager> pullerManager = new StatsPullerManager(); - sp<AlarmMonitor> anomalyAlarmMonitor; - sp<AlarmMonitor> periodicAlarmMonitor; - StatsdConfig config = buildCirclePredicates(); - set<int> allTagIds; - vector<sp<LogMatchingTracker>> allAtomMatchers; - vector<sp<ConditionTracker>> allConditionTrackers; - vector<sp<MetricProducer>> allMetricProducers; - std::vector<sp<AnomalyTracker>> allAnomalyTrackers; - std::vector<sp<AlarmTracker>> allAlarmTrackers; - unordered_map<int, std::vector<int>> conditionToMetricMap; - unordered_map<int, std::vector<int>> trackerToMetricMap; - unordered_map<int, std::vector<int>> trackerToConditionMap; - unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; - unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; - unordered_map<int64_t, int> alertTrackerMap; - vector<int> metricsWithActivation; - std::set<int64_t> noReportMetricIds; - - EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, - periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds, - allAtomMatchers, allConditionTrackers, allMetricProducers, - allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, - trackerToMetricMap, trackerToConditionMap, - activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, - alertTrackerMap, metricsWithActivation, - noReportMetricIds)); -} - -TEST(MetricsManagerTest, testAlertWithUnknownMetric) { - UidMap uidMap; - sp<StatsPullerManager> pullerManager = new StatsPullerManager(); - sp<AlarmMonitor> anomalyAlarmMonitor; - sp<AlarmMonitor> periodicAlarmMonitor; - StatsdConfig config = buildAlertWithUnknownMetric(); - set<int> allTagIds; - vector<sp<LogMatchingTracker>> allAtomMatchers; - vector<sp<ConditionTracker>> allConditionTrackers; - vector<sp<MetricProducer>> allMetricProducers; - std::vector<sp<AnomalyTracker>> allAnomalyTrackers; - std::vector<sp<AlarmTracker>> allAlarmTrackers; - unordered_map<int, std::vector<int>> conditionToMetricMap; - unordered_map<int, std::vector<int>> trackerToMetricMap; - unordered_map<int, std::vector<int>> trackerToConditionMap; - unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; - unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; - unordered_map<int64_t, int> alertTrackerMap; - vector<int> metricsWithActivation; - std::set<int64_t> noReportMetricIds; - - EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, - periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds, - allAtomMatchers, allConditionTrackers, allMetricProducers, - allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, - trackerToMetricMap, trackerToConditionMap, - activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, - alertTrackerMap, metricsWithActivation, - noReportMetricIds)); -} - TEST(MetricsManagerTest, TestLogSources) { string app1 = "app1"; set<int32_t> app1Uids = {1111, 11111}; @@ -680,7 +130,7 @@ TEST(MetricsManagerTest, TestLogSources) { sp<AlarmMonitor> anomalyAlarmMonitor; sp<AlarmMonitor> periodicAlarmMonitor; - StatsdConfig config = buildGoodConfig(); + StatsdConfig config; config.add_allowed_log_source("AID_SYSTEM"); config.add_allowed_log_source(app1); config.add_default_pull_packages("AID_SYSTEM"); @@ -744,7 +194,7 @@ TEST(MetricsManagerTest, TestCheckLogCredentialsWhitelistedAtom) { sp<AlarmMonitor> anomalyAlarmMonitor; sp<AlarmMonitor> periodicAlarmMonitor; - StatsdConfig config = buildGoodConfig(); + StatsdConfig config; config.add_whitelisted_atom_ids(3); config.add_whitelisted_atom_ids(4); diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp index caea42dfe032..d96ff8a1925b 100644 --- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp @@ -47,7 +47,6 @@ namespace { const ConfigKey kConfigKey(0, 12345); const int tagId = 1; const int64_t metricId = 123; -const int64_t atomMatcherId = 678; const int logEventMatcherIndex = 0; const int64_t bucketStartTimeNs = 10 * NS_PER_SEC; const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL; @@ -94,11 +93,8 @@ TEST(GaugeMetricProducerTest, TestFirstBucket) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); - sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({ - new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + sp<EventMatcherWizard> eventMatcherWizard = + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); @@ -127,12 +123,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); @@ -217,12 +209,8 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPushedEvents) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, wizard, logEventMatcherIndex, eventMatcherWizard, @@ -301,12 +289,9 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPulled) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); + sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); @@ -378,12 +363,8 @@ TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); @@ -428,12 +409,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); int64_t conditionChangeNs = bucketStartTimeNs + 8; @@ -502,12 +479,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) { dim->set_field(tagId); dim->add_child()->set_field(1); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); EXPECT_CALL(*wizard, query(_, _, _)) @@ -577,12 +550,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) { gaugeFieldMatcher->set_field(tagId); gaugeFieldMatcher->add_child()->set_field(2); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1, @@ -657,12 +626,8 @@ TEST(GaugeMetricProducerTest, TestPullOnTrigger) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) @@ -729,12 +694,8 @@ TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)) @@ -807,12 +768,8 @@ TEST(GaugeMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 3, _)) diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp index 98892507e78d..5524ebc86b36 100644 --- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp @@ -46,7 +46,6 @@ namespace { const ConfigKey kConfigKey(0, 12345); const int tagId = 1; const int64_t metricId = 123; -const int64_t atomMatcherId = 678; const int logEventMatcherIndex = 0; const int64_t bucketStartTimeNs = 10000000000; const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL; @@ -99,12 +98,8 @@ class ValueMetricProducerTestHelper { public: static sp<ValueMetricProducer> createValueProducerNoConditions( sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) { - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)) .WillOnce(Return()); @@ -122,12 +117,8 @@ public: static sp<ValueMetricProducer> createValueProducerWithCondition( sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric, ConditionState conditionAfterFirstBucketPrepared) { - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)) .WillOnce(Return()); @@ -147,12 +138,8 @@ public: sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric, vector<int32_t> slicedStateAtoms, unordered_map<int, unordered_map<int, int64_t>> stateGroupMap) { - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)) .WillOnce(Return()); @@ -172,12 +159,8 @@ public: vector<int32_t> slicedStateAtoms, unordered_map<int, unordered_map<int, int64_t>> stateGroupMap, ConditionState conditionAfterFirstBucketPrepared) { - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)) .WillOnce(Return()); @@ -237,12 +220,8 @@ TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); int64_t startTimeBase = 11; - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); @@ -267,12 +246,8 @@ TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) { TEST(ValueMetricProducerTest, TestFirstBucket) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); @@ -421,15 +396,11 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPartialBucketCreated) { TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); - auto keyValue = atomMatcher.add_field_value_matcher(); - keyValue->set_field(1); - keyValue->set_eq_int(3); + FieldValueMatcher fvm; + fvm.set_field(1); + fvm.set_eq_int(3); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex, {fvm}); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); @@ -698,12 +669,8 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) { TEST_P(ValueMetricProducerTest_PartialBucket, TestPushedEvents) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); @@ -759,12 +726,8 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPushedEvents) { TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValue) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 150; @@ -820,12 +783,8 @@ TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); metric.set_split_bucket_for_app_upgrade(false); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); @@ -900,12 +859,8 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValueWhileConditionFalse TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); @@ -944,12 +899,8 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) { TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); @@ -1015,12 +966,8 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); @@ -1360,12 +1307,8 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMin) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); metric.set_aggregation_type(ValueMetric::MIN); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); @@ -1404,12 +1347,8 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMax) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); metric.set_aggregation_type(ValueMetric::MAX); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); @@ -1447,12 +1386,8 @@ TEST(ValueMetricProducerTest, TestPushedAggregateAvg) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); metric.set_aggregation_type(ValueMetric::AVG); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); @@ -1495,12 +1430,8 @@ TEST(ValueMetricProducerTest, TestPushedAggregateSum) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); metric.set_aggregation_type(ValueMetric::SUM); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); @@ -1539,12 +1470,8 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) { metric.set_aggregation_type(ValueMetric::MIN); metric.set_use_diff(true); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); @@ -1611,12 +1538,8 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) { metric.set_aggregation_type(ValueMetric::MIN); metric.set_use_diff(true); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); @@ -2140,12 +2063,8 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) { TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) { ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); @@ -2963,12 +2882,8 @@ TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) { TEST(ValueMetricProducerTest, TestPullNeededFastDump) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); @@ -3001,12 +2916,8 @@ TEST(ValueMetricProducerTest, TestPullNeededFastDump) { TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); @@ -3045,12 +2956,8 @@ TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) { TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) { ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); - UidMap uidMap; - SimpleAtomMatcher atomMatcher; - atomMatcher.set_atom_id(tagId); sp<EventMatcherWizard> eventMatcherWizard = - new EventMatcherWizard({new SimpleLogMatchingTracker( - atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + createEventMatcherWizard(tagId, logEventMatcherIndex); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); diff --git a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp new file mode 100644 index 000000000000..6b50fe5387d7 --- /dev/null +++ b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp @@ -0,0 +1,382 @@ +// Copyright (C) 2020 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 "src/metrics/parsing_utils/config_update_utils.h" + +#include <gtest/gtest.h> +#include <private/android_filesystem_config.h> +#include <stdio.h> + +#include <set> +#include <unordered_map> +#include <vector> + +#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" +#include "src/metrics/parsing_utils/metrics_manager_util.h" +#include "tests/statsd_test_util.h" + +using namespace testing; +using android::sp; +using android::os::statsd::Predicate; +using std::map; +using std::set; +using std::unordered_map; +using std::vector; + +#ifdef __ANDROID__ + +namespace android { +namespace os { +namespace statsd { + +namespace { + +ConfigKey key(123, 456); +const int64_t timeBaseNs = 1000; +sp<UidMap> uidMap = new UidMap(); +sp<StatsPullerManager> pullerManager = new StatsPullerManager(); +sp<AlarmMonitor> anomalyAlarmMonitor; +sp<AlarmMonitor> periodicAlarmMonitor; +set<int> allTagIds; +vector<sp<LogMatchingTracker>> oldAtomMatchers; +unordered_map<int64_t, int> oldLogTrackerMap; +vector<sp<ConditionTracker>> oldConditionTrackers; +vector<sp<MetricProducer>> oldMetricProducers; +std::vector<sp<AnomalyTracker>> oldAnomalyTrackers; +std::vector<sp<AlarmTracker>> oldAlarmTrackers; +unordered_map<int, std::vector<int>> conditionToMetricMap; +unordered_map<int, std::vector<int>> trackerToMetricMap; +unordered_map<int, std::vector<int>> trackerToConditionMap; +unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; +unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; +unordered_map<int64_t, int> alertTrackerMap; +vector<int> metricsWithActivation; +std::set<int64_t> noReportMetricIds; + +class ConfigUpdateTest : public ::testing::Test { +public: + ConfigUpdateTest() { + } + + void SetUp() override { + allTagIds.clear(); + oldAtomMatchers.clear(); + oldLogTrackerMap.clear(); + oldConditionTrackers.clear(); + oldMetricProducers.clear(); + oldAnomalyTrackers.clear(); + oldAlarmTrackers.clear(); + conditionToMetricMap.clear(); + trackerToMetricMap.clear(); + trackerToConditionMap.clear(); + activationAtomTrackerToMetricMap.clear(); + deactivationAtomTrackerToMetricMap.clear(); + alertTrackerMap.clear(); + metricsWithActivation.clear(); + noReportMetricIds.clear(); + } +}; + +bool initConfig(const StatsdConfig& config) { + return initStatsdConfig(key, config, uidMap, pullerManager, anomalyAlarmMonitor, + periodicAlarmMonitor, timeBaseNs, timeBaseNs, allTagIds, + oldAtomMatchers, oldLogTrackerMap, oldConditionTrackers, + oldMetricProducers, oldAnomalyTrackers, oldAlarmTrackers, + conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, + activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, + alertTrackerMap, metricsWithActivation, noReportMetricIds); +} + +} // anonymous namespace + +TEST_F(ConfigUpdateTest, TestSimpleMatcherPreserve) { + StatsdConfig config; + AtomMatcher matcher = CreateSimpleAtomMatcher("TEST", /*atom=*/10); + int64_t matcherId = matcher.id(); + *config.add_atom_matcher() = matcher; + + // Create an initial config. + EXPECT_TRUE(initConfig(config)); + + vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN); + vector<bool> cycleTracker(1, false); + unordered_map<int64_t, int> newLogTrackerMap; + newLogTrackerMap[matcherId] = 0; + EXPECT_TRUE(determineMatcherUpdateStatus(config, 0, oldLogTrackerMap, oldAtomMatchers, + newLogTrackerMap, matchersToUpdate, cycleTracker)); + EXPECT_EQ(matchersToUpdate[0], UPDATE_PRESERVE); +} + +TEST_F(ConfigUpdateTest, TestSimpleMatcherReplace) { + StatsdConfig config; + AtomMatcher matcher = CreateSimpleAtomMatcher("TEST", /*atom=*/10); + *config.add_atom_matcher() = matcher; + + EXPECT_TRUE(initConfig(config)); + + StatsdConfig newConfig; + // Same id, different atom, so should be replaced. + AtomMatcher newMatcher = CreateSimpleAtomMatcher("TEST", /*atom=*/11); + int64_t matcherId = newMatcher.id(); + EXPECT_EQ(matcherId, matcher.id()); + *newConfig.add_atom_matcher() = newMatcher; + + vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN); + vector<bool> cycleTracker(1, false); + unordered_map<int64_t, int> newLogTrackerMap; + newLogTrackerMap[matcherId] = 0; + EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 0, oldLogTrackerMap, oldAtomMatchers, + newLogTrackerMap, matchersToUpdate, cycleTracker)); + EXPECT_EQ(matchersToUpdate[0], UPDATE_REPLACE); +} + +TEST_F(ConfigUpdateTest, TestCombinationMatcherPreserve) { + StatsdConfig config; + AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10); + int64_t matcher1Id = matcher1.id(); + *config.add_atom_matcher() = matcher1; + + AtomMatcher matcher2 = CreateSimpleAtomMatcher("TEST2", /*atom=*/11); + *config.add_atom_matcher() = matcher2; + int64_t matcher2Id = matcher2.id(); + + AtomMatcher matcher3; + matcher3.set_id(StringToId("TEST3")); + AtomMatcher_Combination* combination = matcher3.mutable_combination(); + combination->set_operation(LogicalOperation::OR); + combination->add_matcher(matcher1Id); + combination->add_matcher(matcher2Id); + int64_t matcher3Id = matcher3.id(); + *config.add_atom_matcher() = matcher3; + + EXPECT_TRUE(initConfig(config)); + + StatsdConfig newConfig; + unordered_map<int64_t, int> newLogTrackerMap; + // Same matchers, different order, all should be preserved. + *newConfig.add_atom_matcher() = matcher2; + newLogTrackerMap[matcher2Id] = 0; + *newConfig.add_atom_matcher() = matcher3; + newLogTrackerMap[matcher3Id] = 1; + *newConfig.add_atom_matcher() = matcher1; + newLogTrackerMap[matcher1Id] = 2; + + vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN); + vector<bool> cycleTracker(3, false); + // Only update the combination. It should recurse the two child matchers and preserve all 3. + EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldLogTrackerMap, oldAtomMatchers, + newLogTrackerMap, matchersToUpdate, cycleTracker)); + EXPECT_EQ(matchersToUpdate[0], UPDATE_PRESERVE); + EXPECT_EQ(matchersToUpdate[1], UPDATE_PRESERVE); + EXPECT_EQ(matchersToUpdate[2], UPDATE_PRESERVE); +} + +TEST_F(ConfigUpdateTest, TestCombinationMatcherReplace) { + StatsdConfig config; + AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10); + int64_t matcher1Id = matcher1.id(); + *config.add_atom_matcher() = matcher1; + + AtomMatcher matcher2 = CreateSimpleAtomMatcher("TEST2", /*atom=*/11); + *config.add_atom_matcher() = matcher2; + int64_t matcher2Id = matcher2.id(); + + AtomMatcher matcher3; + matcher3.set_id(StringToId("TEST3")); + AtomMatcher_Combination* combination = matcher3.mutable_combination(); + combination->set_operation(LogicalOperation::OR); + combination->add_matcher(matcher1Id); + combination->add_matcher(matcher2Id); + int64_t matcher3Id = matcher3.id(); + *config.add_atom_matcher() = matcher3; + + EXPECT_TRUE(initConfig(config)); + + // Change the logical operation of the combination matcher, causing a replacement. + matcher3.mutable_combination()->set_operation(LogicalOperation::AND); + + StatsdConfig newConfig; + unordered_map<int64_t, int> newLogTrackerMap; + *newConfig.add_atom_matcher() = matcher2; + newLogTrackerMap[matcher2Id] = 0; + *newConfig.add_atom_matcher() = matcher3; + newLogTrackerMap[matcher3Id] = 1; + *newConfig.add_atom_matcher() = matcher1; + newLogTrackerMap[matcher1Id] = 2; + + vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN); + vector<bool> cycleTracker(3, false); + // Only update the combination. The simple matchers should not be evaluated. + EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldLogTrackerMap, oldAtomMatchers, + newLogTrackerMap, matchersToUpdate, cycleTracker)); + EXPECT_EQ(matchersToUpdate[0], UPDATE_UNKNOWN); + EXPECT_EQ(matchersToUpdate[1], UPDATE_REPLACE); + EXPECT_EQ(matchersToUpdate[2], UPDATE_UNKNOWN); +} + +TEST_F(ConfigUpdateTest, TestCombinationMatcherDepsChange) { + StatsdConfig config; + AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10); + int64_t matcher1Id = matcher1.id(); + *config.add_atom_matcher() = matcher1; + + AtomMatcher matcher2 = CreateSimpleAtomMatcher("TEST2", /*atom=*/11); + *config.add_atom_matcher() = matcher2; + int64_t matcher2Id = matcher2.id(); + + AtomMatcher matcher3; + matcher3.set_id(StringToId("TEST3")); + AtomMatcher_Combination* combination = matcher3.mutable_combination(); + combination->set_operation(LogicalOperation::OR); + combination->add_matcher(matcher1Id); + combination->add_matcher(matcher2Id); + int64_t matcher3Id = matcher3.id(); + *config.add_atom_matcher() = matcher3; + + EXPECT_TRUE(initConfig(config)); + + // Change a dependency of matcher 3. + matcher2.mutable_simple_atom_matcher()->set_atom_id(12); + + StatsdConfig newConfig; + unordered_map<int64_t, int> newLogTrackerMap; + *newConfig.add_atom_matcher() = matcher2; + newLogTrackerMap[matcher2Id] = 0; + *newConfig.add_atom_matcher() = matcher3; + newLogTrackerMap[matcher3Id] = 1; + *newConfig.add_atom_matcher() = matcher1; + newLogTrackerMap[matcher1Id] = 2; + + vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN); + vector<bool> cycleTracker(3, false); + // Only update the combination. + EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldLogTrackerMap, oldAtomMatchers, + newLogTrackerMap, matchersToUpdate, cycleTracker)); + // Matcher 2 and matcher3 must be reevaluated. Matcher 1 might, but does not need to be. + EXPECT_EQ(matchersToUpdate[0], UPDATE_REPLACE); + EXPECT_EQ(matchersToUpdate[1], UPDATE_REPLACE); +} + +TEST_F(ConfigUpdateTest, TestUpdateMatchers) { + StatsdConfig config; + // Will be preserved. + AtomMatcher simple1 = CreateSimpleAtomMatcher("SIMPLE1", /*atom=*/10); + int64_t simple1Id = simple1.id(); + *config.add_atom_matcher() = simple1; + + // Will be replaced. + AtomMatcher simple2 = CreateSimpleAtomMatcher("SIMPLE2", /*atom=*/11); + *config.add_atom_matcher() = simple2; + int64_t simple2Id = simple2.id(); + + // Will be removed. + AtomMatcher simple3 = CreateSimpleAtomMatcher("SIMPLE3", /*atom=*/12); + *config.add_atom_matcher() = simple3; + int64_t simple3Id = simple3.id(); + + // Will be preserved. + AtomMatcher combination1; + combination1.set_id(StringToId("combination1")); + AtomMatcher_Combination* combination = combination1.mutable_combination(); + combination->set_operation(LogicalOperation::NOT); + combination->add_matcher(simple1Id); + int64_t combination1Id = combination1.id(); + *config.add_atom_matcher() = combination1; + + // Will be replaced since it depends on simple2. + AtomMatcher combination2; + combination2.set_id(StringToId("combination2")); + combination = combination2.mutable_combination(); + combination->set_operation(LogicalOperation::AND); + combination->add_matcher(simple1Id); + combination->add_matcher(simple2Id); + int64_t combination2Id = combination2.id(); + *config.add_atom_matcher() = combination2; + + EXPECT_TRUE(initConfig(config)); + + // Change simple2, causing simple2 and combination2 to be replaced. + simple2.mutable_simple_atom_matcher()->set_atom_id(111); + + // 2 new matchers: simple4 and combination3: + AtomMatcher simple4 = CreateSimpleAtomMatcher("SIMPLE4", /*atom=*/13); + int64_t simple4Id = simple4.id(); + + AtomMatcher combination3; + combination3.set_id(StringToId("combination3")); + combination = combination3.mutable_combination(); + combination->set_operation(LogicalOperation::AND); + combination->add_matcher(simple4Id); + combination->add_matcher(simple2Id); + int64_t combination3Id = combination3.id(); + + StatsdConfig newConfig; + *newConfig.add_atom_matcher() = combination3; + *newConfig.add_atom_matcher() = simple2; + *newConfig.add_atom_matcher() = combination2; + *newConfig.add_atom_matcher() = simple1; + *newConfig.add_atom_matcher() = simple4; + *newConfig.add_atom_matcher() = combination1; + + set<int> newTagIds; + unordered_map<int64_t, int> newLogTrackerMap; + vector<sp<LogMatchingTracker>> newAtomMatchers; + EXPECT_TRUE(updateLogTrackers(newConfig, uidMap, oldLogTrackerMap, oldAtomMatchers, newTagIds, + newLogTrackerMap, newAtomMatchers)); + + ASSERT_EQ(newTagIds.size(), 3); + EXPECT_EQ(newTagIds.count(10), 1); + EXPECT_EQ(newTagIds.count(111), 1); + EXPECT_EQ(newTagIds.count(13), 1); + + ASSERT_EQ(newLogTrackerMap.size(), 6); + EXPECT_EQ(newLogTrackerMap.at(combination3Id), 0); + EXPECT_EQ(newLogTrackerMap.at(simple2Id), 1); + EXPECT_EQ(newLogTrackerMap.at(combination2Id), 2); + EXPECT_EQ(newLogTrackerMap.at(simple1Id), 3); + EXPECT_EQ(newLogTrackerMap.at(simple4Id), 4); + EXPECT_EQ(newLogTrackerMap.at(combination1Id), 5); + + ASSERT_EQ(newAtomMatchers.size(), 6); + // Make sure all atom matchers are initialized: + for (const sp<LogMatchingTracker>& tracker : newAtomMatchers) { + EXPECT_TRUE(tracker->mInitialized); + } + // Make sure preserved atom matchers are the same. + EXPECT_EQ(oldAtomMatchers[oldLogTrackerMap.at(simple1Id)], + newAtomMatchers[newLogTrackerMap.at(simple1Id)]); + EXPECT_EQ(oldAtomMatchers[oldLogTrackerMap.at(combination1Id)], + newAtomMatchers[newLogTrackerMap.at(combination1Id)]); + // Make sure replaced matchers are different. + EXPECT_NE(oldAtomMatchers[oldLogTrackerMap.at(simple2Id)], + newAtomMatchers[newLogTrackerMap.at(simple2Id)]); + EXPECT_NE(oldAtomMatchers[oldLogTrackerMap.at(combination2Id)], + newAtomMatchers[newLogTrackerMap.at(combination2Id)]); + + // Validation, make sure the matchers have the proper ids. Could do more checks here. + EXPECT_EQ(newAtomMatchers[0]->getId(), combination3Id); + EXPECT_EQ(newAtomMatchers[1]->getId(), simple2Id); + EXPECT_EQ(newAtomMatchers[2]->getId(), combination2Id); + EXPECT_EQ(newAtomMatchers[3]->getId(), simple1Id); + EXPECT_EQ(newAtomMatchers[4]->getId(), simple4Id); + EXPECT_EQ(newAtomMatchers[5]->getId(), combination1Id); +} + +} // namespace statsd +} // namespace os +} // namespace android + +#else +GTEST_LOG_(INFO) << "This test does nothing.\n"; +#endif diff --git a/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp new file mode 100644 index 000000000000..4e97eaf6f149 --- /dev/null +++ b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp @@ -0,0 +1,708 @@ +// Copyright (C) 2020 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 "src/metrics/parsing_utils/metrics_manager_util.h" + +#include <gtest/gtest.h> +#include <private/android_filesystem_config.h> +#include <stdio.h> + +#include <set> +#include <unordered_map> +#include <vector> + +#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" +#include "src/condition/ConditionTracker.h" +#include "src/matchers/LogMatchingTracker.h" +#include "src/metrics/CountMetricProducer.h" +#include "src/metrics/GaugeMetricProducer.h" +#include "src/metrics/MetricProducer.h" +#include "src/metrics/ValueMetricProducer.h" +#include "src/state/StateManager.h" +#include "tests/metrics/metrics_test_helper.h" +#include "tests/statsd_test_util.h" + +using namespace testing; +using android::sp; +using android::os::statsd::Predicate; +using std::map; +using std::set; +using std::unordered_map; +using std::vector; + +#ifdef __ANDROID__ + +namespace android { +namespace os { +namespace statsd { + +namespace { +const ConfigKey kConfigKey(0, 12345); +const long kAlertId = 3; + +const long timeBaseSec = 1000; + +StatsdConfig buildGoodConfig() { + StatsdConfig config; + config.set_id(12345); + + AtomMatcher* eventMatcher = config.add_atom_matcher(); + eventMatcher->set_id(StringToId("SCREEN_IS_ON")); + + SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); + simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); + simpleAtomMatcher->add_field_value_matcher()->set_field( + 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); + simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( + 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/); + + eventMatcher = config.add_atom_matcher(); + eventMatcher->set_id(StringToId("SCREEN_IS_OFF")); + + simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); + simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); + simpleAtomMatcher->add_field_value_matcher()->set_field( + 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); + simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( + 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/); + + eventMatcher = config.add_atom_matcher(); + eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF")); + + AtomMatcher_Combination* combination = eventMatcher->mutable_combination(); + combination->set_operation(LogicalOperation::OR); + combination->add_matcher(StringToId("SCREEN_IS_ON")); + combination->add_matcher(StringToId("SCREEN_IS_OFF")); + + CountMetric* metric = config.add_count_metric(); + metric->set_id(3); + metric->set_what(StringToId("SCREEN_IS_ON")); + metric->set_bucket(ONE_MINUTE); + metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/); + metric->mutable_dimensions_in_what()->add_child()->set_field(1); + + config.add_no_report_metric(3); + + auto alert = config.add_alert(); + alert->set_id(kAlertId); + alert->set_metric_id(3); + alert->set_num_buckets(10); + alert->set_refractory_period_secs(100); + alert->set_trigger_if_sum_gt(100); + return config; +} + +StatsdConfig buildCircleMatchers() { + StatsdConfig config; + config.set_id(12345); + + AtomMatcher* eventMatcher = config.add_atom_matcher(); + eventMatcher->set_id(StringToId("SCREEN_IS_ON")); + + SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); + simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); + simpleAtomMatcher->add_field_value_matcher()->set_field( + 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); + simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( + 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/); + + eventMatcher = config.add_atom_matcher(); + eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF")); + + AtomMatcher_Combination* combination = eventMatcher->mutable_combination(); + combination->set_operation(LogicalOperation::OR); + combination->add_matcher(StringToId("SCREEN_IS_ON")); + // Circle dependency + combination->add_matcher(StringToId("SCREEN_ON_OR_OFF")); + + return config; +} + +StatsdConfig buildAlertWithUnknownMetric() { + StatsdConfig config; + config.set_id(12345); + + AtomMatcher* eventMatcher = config.add_atom_matcher(); + eventMatcher->set_id(StringToId("SCREEN_IS_ON")); + + CountMetric* metric = config.add_count_metric(); + metric->set_id(3); + metric->set_what(StringToId("SCREEN_IS_ON")); + metric->set_bucket(ONE_MINUTE); + metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/); + metric->mutable_dimensions_in_what()->add_child()->set_field(1); + + auto alert = config.add_alert(); + alert->set_id(3); + alert->set_metric_id(2); + alert->set_num_buckets(10); + alert->set_refractory_period_secs(100); + alert->set_trigger_if_sum_gt(100); + return config; +} + +StatsdConfig buildMissingMatchers() { + StatsdConfig config; + config.set_id(12345); + + AtomMatcher* eventMatcher = config.add_atom_matcher(); + eventMatcher->set_id(StringToId("SCREEN_IS_ON")); + + SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); + simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); + simpleAtomMatcher->add_field_value_matcher()->set_field( + 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); + simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( + 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/); + + eventMatcher = config.add_atom_matcher(); + eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF")); + + AtomMatcher_Combination* combination = eventMatcher->mutable_combination(); + combination->set_operation(LogicalOperation::OR); + combination->add_matcher(StringToId("SCREEN_IS_ON")); + // undefined matcher + combination->add_matcher(StringToId("ABC")); + + return config; +} + +StatsdConfig buildMissingPredicate() { + StatsdConfig config; + config.set_id(12345); + + CountMetric* metric = config.add_count_metric(); + metric->set_id(3); + metric->set_what(StringToId("SCREEN_EVENT")); + metric->set_bucket(ONE_MINUTE); + metric->set_condition(StringToId("SOME_CONDITION")); + + AtomMatcher* eventMatcher = config.add_atom_matcher(); + eventMatcher->set_id(StringToId("SCREEN_EVENT")); + + SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); + simpleAtomMatcher->set_atom_id(2); + + return config; +} + +StatsdConfig buildDimensionMetricsWithMultiTags() { + StatsdConfig config; + config.set_id(12345); + + AtomMatcher* eventMatcher = config.add_atom_matcher(); + eventMatcher->set_id(StringToId("BATTERY_VERY_LOW")); + SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); + simpleAtomMatcher->set_atom_id(2); + + eventMatcher = config.add_atom_matcher(); + eventMatcher->set_id(StringToId("BATTERY_VERY_VERY_LOW")); + simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); + simpleAtomMatcher->set_atom_id(3); + + eventMatcher = config.add_atom_matcher(); + eventMatcher->set_id(StringToId("BATTERY_LOW")); + + AtomMatcher_Combination* combination = eventMatcher->mutable_combination(); + combination->set_operation(LogicalOperation::OR); + combination->add_matcher(StringToId("BATTERY_VERY_LOW")); + combination->add_matcher(StringToId("BATTERY_VERY_VERY_LOW")); + + // Count process state changes, slice by uid, while SCREEN_IS_OFF + CountMetric* metric = config.add_count_metric(); + metric->set_id(3); + metric->set_what(StringToId("BATTERY_LOW")); + metric->set_bucket(ONE_MINUTE); + // This case is interesting. We want to dimension across two atoms. + metric->mutable_dimensions_in_what()->add_child()->set_field(1); + + auto alert = config.add_alert(); + alert->set_id(kAlertId); + alert->set_metric_id(3); + alert->set_num_buckets(10); + alert->set_refractory_period_secs(100); + alert->set_trigger_if_sum_gt(100); + return config; +} + +StatsdConfig buildCirclePredicates() { + StatsdConfig config; + config.set_id(12345); + + AtomMatcher* eventMatcher = config.add_atom_matcher(); + eventMatcher->set_id(StringToId("SCREEN_IS_ON")); + + SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); + simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); + simpleAtomMatcher->add_field_value_matcher()->set_field( + 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); + simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( + 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/); + + eventMatcher = config.add_atom_matcher(); + eventMatcher->set_id(StringToId("SCREEN_IS_OFF")); + + simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); + simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); + simpleAtomMatcher->add_field_value_matcher()->set_field( + 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); + simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( + 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/); + + auto condition = config.add_predicate(); + condition->set_id(StringToId("SCREEN_IS_ON")); + SimplePredicate* simplePredicate = condition->mutable_simple_predicate(); + simplePredicate->set_start(StringToId("SCREEN_IS_ON")); + simplePredicate->set_stop(StringToId("SCREEN_IS_OFF")); + + condition = config.add_predicate(); + condition->set_id(StringToId("SCREEN_IS_EITHER_ON_OFF")); + + Predicate_Combination* combination = condition->mutable_combination(); + combination->set_operation(LogicalOperation::OR); + combination->add_predicate(StringToId("SCREEN_IS_ON")); + combination->add_predicate(StringToId("SCREEN_IS_EITHER_ON_OFF")); + + return config; +} + +StatsdConfig buildConfigWithDifferentPredicates() { + StatsdConfig config; + config.set_id(12345); + + auto pulledAtomMatcher = + CreateSimpleAtomMatcher("SUBSYSTEM_SLEEP", util::SUBSYSTEM_SLEEP_STATE); + *config.add_atom_matcher() = pulledAtomMatcher; + auto screenOnAtomMatcher = CreateScreenTurnedOnAtomMatcher(); + *config.add_atom_matcher() = screenOnAtomMatcher; + auto screenOffAtomMatcher = CreateScreenTurnedOffAtomMatcher(); + *config.add_atom_matcher() = screenOffAtomMatcher; + auto batteryNoneAtomMatcher = CreateBatteryStateNoneMatcher(); + *config.add_atom_matcher() = batteryNoneAtomMatcher; + auto batteryUsbAtomMatcher = CreateBatteryStateUsbMatcher(); + *config.add_atom_matcher() = batteryUsbAtomMatcher; + + // Simple condition with InitialValue set to default (unknown). + auto screenOnUnknownPredicate = CreateScreenIsOnPredicate(); + *config.add_predicate() = screenOnUnknownPredicate; + + // Simple condition with InitialValue set to false. + auto screenOnFalsePredicate = config.add_predicate(); + screenOnFalsePredicate->set_id(StringToId("ScreenIsOnInitialFalse")); + SimplePredicate* simpleScreenOnFalsePredicate = + screenOnFalsePredicate->mutable_simple_predicate(); + simpleScreenOnFalsePredicate->set_start(screenOnAtomMatcher.id()); + simpleScreenOnFalsePredicate->set_stop(screenOffAtomMatcher.id()); + simpleScreenOnFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE); + + // Simple condition with InitialValue set to false. + auto onBatteryFalsePredicate = config.add_predicate(); + onBatteryFalsePredicate->set_id(StringToId("OnBatteryInitialFalse")); + SimplePredicate* simpleOnBatteryFalsePredicate = + onBatteryFalsePredicate->mutable_simple_predicate(); + simpleOnBatteryFalsePredicate->set_start(batteryNoneAtomMatcher.id()); + simpleOnBatteryFalsePredicate->set_stop(batteryUsbAtomMatcher.id()); + simpleOnBatteryFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE); + + // Combination condition with both simple condition InitialValues set to false. + auto screenOnFalseOnBatteryFalsePredicate = config.add_predicate(); + screenOnFalseOnBatteryFalsePredicate->set_id(StringToId("ScreenOnFalseOnBatteryFalse")); + screenOnFalseOnBatteryFalsePredicate->mutable_combination()->set_operation( + LogicalOperation::AND); + addPredicateToPredicateCombination(*screenOnFalsePredicate, + screenOnFalseOnBatteryFalsePredicate); + addPredicateToPredicateCombination(*onBatteryFalsePredicate, + screenOnFalseOnBatteryFalsePredicate); + + // Combination condition with one simple condition InitialValue set to unknown and one set to + // false. + auto screenOnUnknownOnBatteryFalsePredicate = config.add_predicate(); + screenOnUnknownOnBatteryFalsePredicate->set_id(StringToId("ScreenOnUnknowneOnBatteryFalse")); + screenOnUnknownOnBatteryFalsePredicate->mutable_combination()->set_operation( + LogicalOperation::AND); + addPredicateToPredicateCombination(screenOnUnknownPredicate, + screenOnUnknownOnBatteryFalsePredicate); + addPredicateToPredicateCombination(*onBatteryFalsePredicate, + screenOnUnknownOnBatteryFalsePredicate); + + // Simple condition metric with initial value false. + ValueMetric* metric1 = config.add_value_metric(); + metric1->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialFalse")); + metric1->set_what(pulledAtomMatcher.id()); + *metric1->mutable_value_field() = + CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); + metric1->set_bucket(FIVE_MINUTES); + metric1->set_condition(screenOnFalsePredicate->id()); + + // Simple condition metric with initial value unknown. + ValueMetric* metric2 = config.add_value_metric(); + metric2->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialUnknown")); + metric2->set_what(pulledAtomMatcher.id()); + *metric2->mutable_value_field() = + CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); + metric2->set_bucket(FIVE_MINUTES); + metric2->set_condition(screenOnUnknownPredicate.id()); + + // Combination condition metric with initial values false and false. + ValueMetric* metric3 = config.add_value_metric(); + metric3->set_id(StringToId("ValueSubsystemSleepWhileScreenOnFalseDeviceUnpluggedFalse")); + metric3->set_what(pulledAtomMatcher.id()); + *metric3->mutable_value_field() = + CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); + metric3->set_bucket(FIVE_MINUTES); + metric3->set_condition(screenOnFalseOnBatteryFalsePredicate->id()); + + // Combination condition metric with initial values unknown and false. + ValueMetric* metric4 = config.add_value_metric(); + metric4->set_id(StringToId("ValueSubsystemSleepWhileScreenOnUnknownDeviceUnpluggedFalse")); + metric4->set_what(pulledAtomMatcher.id()); + *metric4->mutable_value_field() = + CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); + metric4->set_bucket(FIVE_MINUTES); + metric4->set_condition(screenOnUnknownOnBatteryFalsePredicate->id()); + + return config; +} +} // anonymous namespace + +TEST(MetricsManagerTest, TestInitialConditions) { + sp<UidMap> uidMap = new UidMap(); + sp<StatsPullerManager> pullerManager = new StatsPullerManager(); + sp<AlarmMonitor> anomalyAlarmMonitor; + sp<AlarmMonitor> periodicAlarmMonitor; + StatsdConfig config = buildConfigWithDifferentPredicates(); + set<int> allTagIds; + vector<sp<LogMatchingTracker>> allAtomMatchers; + unordered_map<int64_t, int> logTrackerMap; + vector<sp<ConditionTracker>> allConditionTrackers; + vector<sp<MetricProducer>> allMetricProducers; + std::vector<sp<AnomalyTracker>> allAnomalyTrackers; + std::vector<sp<AlarmTracker>> allAlarmTrackers; + unordered_map<int, std::vector<int>> conditionToMetricMap; + unordered_map<int, std::vector<int>> trackerToMetricMap; + unordered_map<int, std::vector<int>> trackerToConditionMap; + unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; + unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; + unordered_map<int64_t, int> alertTrackerMap; + vector<int> metricsWithActivation; + std::set<int64_t> noReportMetricIds; + + EXPECT_TRUE(initStatsdConfig( + kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap, + allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers, + conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, + activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, + metricsWithActivation, noReportMetricIds)); + ASSERT_EQ(4u, allMetricProducers.size()); + ASSERT_EQ(5u, allConditionTrackers.size()); + + ConditionKey queryKey; + vector<ConditionState> conditionCache(5, ConditionState::kNotEvaluated); + + allConditionTrackers[3]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache); + allConditionTrackers[4]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache); + EXPECT_EQ(ConditionState::kUnknown, conditionCache[0]); + EXPECT_EQ(ConditionState::kFalse, conditionCache[1]); + EXPECT_EQ(ConditionState::kFalse, conditionCache[2]); + EXPECT_EQ(ConditionState::kFalse, conditionCache[3]); + EXPECT_EQ(ConditionState::kUnknown, conditionCache[4]); + + EXPECT_EQ(ConditionState::kFalse, allMetricProducers[0]->mCondition); + EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[1]->mCondition); + EXPECT_EQ(ConditionState::kFalse, allMetricProducers[2]->mCondition); + EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[3]->mCondition); +} + +TEST(MetricsManagerTest, TestGoodConfig) { + sp<UidMap> uidMap = new UidMap(); + sp<StatsPullerManager> pullerManager = new StatsPullerManager(); + sp<AlarmMonitor> anomalyAlarmMonitor; + sp<AlarmMonitor> periodicAlarmMonitor; + StatsdConfig config = buildGoodConfig(); + set<int> allTagIds; + vector<sp<LogMatchingTracker>> allAtomMatchers; + unordered_map<int64_t, int> logTrackerMap; + vector<sp<ConditionTracker>> allConditionTrackers; + vector<sp<MetricProducer>> allMetricProducers; + std::vector<sp<AnomalyTracker>> allAnomalyTrackers; + std::vector<sp<AlarmTracker>> allAlarmTrackers; + unordered_map<int, std::vector<int>> conditionToMetricMap; + unordered_map<int, std::vector<int>> trackerToMetricMap; + unordered_map<int, std::vector<int>> trackerToConditionMap; + unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; + unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; + unordered_map<int64_t, int> alertTrackerMap; + vector<int> metricsWithActivation; + std::set<int64_t> noReportMetricIds; + + EXPECT_TRUE(initStatsdConfig( + kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap, + allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers, + conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, + activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, + metricsWithActivation, noReportMetricIds)); + ASSERT_EQ(1u, allMetricProducers.size()); + ASSERT_EQ(1u, allAnomalyTrackers.size()); + ASSERT_EQ(1u, noReportMetricIds.size()); + ASSERT_EQ(1u, alertTrackerMap.size()); + EXPECT_NE(alertTrackerMap.find(kAlertId), alertTrackerMap.end()); + EXPECT_EQ(alertTrackerMap.find(kAlertId)->second, 0); +} + +TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) { + sp<UidMap> uidMap = new UidMap(); + sp<StatsPullerManager> pullerManager = new StatsPullerManager(); + sp<AlarmMonitor> anomalyAlarmMonitor; + sp<AlarmMonitor> periodicAlarmMonitor; + StatsdConfig config = buildDimensionMetricsWithMultiTags(); + set<int> allTagIds; + vector<sp<LogMatchingTracker>> allAtomMatchers; + unordered_map<int64_t, int> logTrackerMap; + vector<sp<ConditionTracker>> allConditionTrackers; + vector<sp<MetricProducer>> allMetricProducers; + std::vector<sp<AnomalyTracker>> allAnomalyTrackers; + std::vector<sp<AlarmTracker>> allAlarmTrackers; + unordered_map<int, std::vector<int>> conditionToMetricMap; + unordered_map<int, std::vector<int>> trackerToMetricMap; + unordered_map<int, std::vector<int>> trackerToConditionMap; + unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; + unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; + unordered_map<int64_t, int> alertTrackerMap; + vector<int> metricsWithActivation; + std::set<int64_t> noReportMetricIds; + + EXPECT_FALSE(initStatsdConfig( + kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap, + allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers, + conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, + activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, + metricsWithActivation, noReportMetricIds)); +} + +TEST(MetricsManagerTest, TestCircleLogMatcherDependency) { + sp<UidMap> uidMap = new UidMap(); + sp<StatsPullerManager> pullerManager = new StatsPullerManager(); + sp<AlarmMonitor> anomalyAlarmMonitor; + sp<AlarmMonitor> periodicAlarmMonitor; + StatsdConfig config = buildCircleMatchers(); + set<int> allTagIds; + vector<sp<LogMatchingTracker>> allAtomMatchers; + unordered_map<int64_t, int> logTrackerMap; + vector<sp<ConditionTracker>> allConditionTrackers; + vector<sp<MetricProducer>> allMetricProducers; + std::vector<sp<AnomalyTracker>> allAnomalyTrackers; + std::vector<sp<AlarmTracker>> allAlarmTrackers; + unordered_map<int, std::vector<int>> conditionToMetricMap; + unordered_map<int, std::vector<int>> trackerToMetricMap; + unordered_map<int, std::vector<int>> trackerToConditionMap; + unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; + unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; + unordered_map<int64_t, int> alertTrackerMap; + vector<int> metricsWithActivation; + std::set<int64_t> noReportMetricIds; + + EXPECT_FALSE(initStatsdConfig( + kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap, + allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers, + conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, + activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, + metricsWithActivation, noReportMetricIds)); +} + +TEST(MetricsManagerTest, TestMissingMatchers) { + sp<UidMap> uidMap = new UidMap(); + sp<StatsPullerManager> pullerManager = new StatsPullerManager(); + sp<AlarmMonitor> anomalyAlarmMonitor; + sp<AlarmMonitor> periodicAlarmMonitor; + StatsdConfig config = buildMissingMatchers(); + set<int> allTagIds; + vector<sp<LogMatchingTracker>> allAtomMatchers; + unordered_map<int64_t, int> logTrackerMap; + vector<sp<ConditionTracker>> allConditionTrackers; + vector<sp<MetricProducer>> allMetricProducers; + std::vector<sp<AnomalyTracker>> allAnomalyTrackers; + std::vector<sp<AlarmTracker>> allAlarmTrackers; + unordered_map<int, std::vector<int>> conditionToMetricMap; + unordered_map<int, std::vector<int>> trackerToMetricMap; + unordered_map<int, std::vector<int>> trackerToConditionMap; + unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; + unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; + unordered_map<int64_t, int> alertTrackerMap; + vector<int> metricsWithActivation; + std::set<int64_t> noReportMetricIds; + EXPECT_FALSE(initStatsdConfig( + kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap, + allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers, + conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, + activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, + metricsWithActivation, noReportMetricIds)); +} + +TEST(MetricsManagerTest, TestMissingPredicate) { + sp<UidMap> uidMap = new UidMap(); + sp<StatsPullerManager> pullerManager = new StatsPullerManager(); + sp<AlarmMonitor> anomalyAlarmMonitor; + sp<AlarmMonitor> periodicAlarmMonitor; + StatsdConfig config = buildMissingPredicate(); + set<int> allTagIds; + vector<sp<LogMatchingTracker>> allAtomMatchers; + unordered_map<int64_t, int> logTrackerMap; + vector<sp<ConditionTracker>> allConditionTrackers; + vector<sp<MetricProducer>> allMetricProducers; + std::vector<sp<AnomalyTracker>> allAnomalyTrackers; + std::vector<sp<AlarmTracker>> allAlarmTrackers; + unordered_map<int, std::vector<int>> conditionToMetricMap; + unordered_map<int, std::vector<int>> trackerToMetricMap; + unordered_map<int, std::vector<int>> trackerToConditionMap; + unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; + unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; + unordered_map<int64_t, int> alertTrackerMap; + vector<int> metricsWithActivation; + std::set<int64_t> noReportMetricIds; + EXPECT_FALSE(initStatsdConfig( + kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap, + allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers, + conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, + activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, + metricsWithActivation, noReportMetricIds)); +} + +TEST(MetricsManagerTest, TestCirclePredicateDependency) { + sp<UidMap> uidMap = new UidMap(); + sp<StatsPullerManager> pullerManager = new StatsPullerManager(); + sp<AlarmMonitor> anomalyAlarmMonitor; + sp<AlarmMonitor> periodicAlarmMonitor; + StatsdConfig config = buildCirclePredicates(); + set<int> allTagIds; + vector<sp<LogMatchingTracker>> allAtomMatchers; + unordered_map<int64_t, int> logTrackerMap; + vector<sp<ConditionTracker>> allConditionTrackers; + vector<sp<MetricProducer>> allMetricProducers; + std::vector<sp<AnomalyTracker>> allAnomalyTrackers; + std::vector<sp<AlarmTracker>> allAlarmTrackers; + unordered_map<int, std::vector<int>> conditionToMetricMap; + unordered_map<int, std::vector<int>> trackerToMetricMap; + unordered_map<int, std::vector<int>> trackerToConditionMap; + unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; + unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; + unordered_map<int64_t, int> alertTrackerMap; + vector<int> metricsWithActivation; + std::set<int64_t> noReportMetricIds; + + EXPECT_FALSE(initStatsdConfig( + kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap, + allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers, + conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, + activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, + metricsWithActivation, noReportMetricIds)); +} + +TEST(MetricsManagerTest, testAlertWithUnknownMetric) { + sp<UidMap> uidMap = new UidMap(); + sp<StatsPullerManager> pullerManager = new StatsPullerManager(); + sp<AlarmMonitor> anomalyAlarmMonitor; + sp<AlarmMonitor> periodicAlarmMonitor; + StatsdConfig config = buildAlertWithUnknownMetric(); + set<int> allTagIds; + vector<sp<LogMatchingTracker>> allAtomMatchers; + unordered_map<int64_t, int> logTrackerMap; + vector<sp<ConditionTracker>> allConditionTrackers; + vector<sp<MetricProducer>> allMetricProducers; + std::vector<sp<AnomalyTracker>> allAnomalyTrackers; + std::vector<sp<AlarmTracker>> allAlarmTrackers; + unordered_map<int, std::vector<int>> conditionToMetricMap; + unordered_map<int, std::vector<int>> trackerToMetricMap; + unordered_map<int, std::vector<int>> trackerToConditionMap; + unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap; + unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap; + unordered_map<int64_t, int> alertTrackerMap; + vector<int> metricsWithActivation; + std::set<int64_t> noReportMetricIds; + + EXPECT_FALSE(initStatsdConfig( + kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap, + allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers, + conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, + activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, + metricsWithActivation, noReportMetricIds)); +} + +TEST(MetricsManagerTest, TestCreateLogTrackerInvalidMatcher) { + sp<UidMap> uidMap = new UidMap(); + AtomMatcher matcher; + matcher.set_id(21); + EXPECT_EQ(createLogTracker(matcher, 0, uidMap), nullptr); +} + +TEST(MetricsManagerTest, TestCreateLogTrackerSimple) { + int index = 1; + int64_t id = 123; + sp<UidMap> uidMap = new UidMap(); + AtomMatcher matcher; + matcher.set_id(id); + SimpleAtomMatcher* simpleAtomMatcher = matcher.mutable_simple_atom_matcher(); + simpleAtomMatcher->set_atom_id(util::SCREEN_STATE_CHANGED); + simpleAtomMatcher->add_field_value_matcher()->set_field( + 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); + simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( + android::view::DisplayStateEnum::DISPLAY_STATE_ON); + + sp<LogMatchingTracker> tracker = createLogTracker(matcher, index, uidMap); + EXPECT_NE(tracker, nullptr); + + EXPECT_TRUE(tracker->mInitialized); + EXPECT_EQ(tracker->getId(), id); + EXPECT_EQ(tracker->mIndex, index); + const set<int>& atomIds = tracker->getAtomIds(); + ASSERT_EQ(atomIds.size(), 1); + EXPECT_EQ(atomIds.count(util::SCREEN_STATE_CHANGED), 1); +} + +TEST(MetricsManagerTest, TestCreateLogTrackerCombination) { + int index = 1; + int64_t id = 123; + sp<UidMap> uidMap = new UidMap(); + AtomMatcher matcher; + matcher.set_id(id); + AtomMatcher_Combination* combination = matcher.mutable_combination(); + combination->set_operation(LogicalOperation::OR); + combination->add_matcher(123); + combination->add_matcher(223); + + sp<LogMatchingTracker> tracker = createLogTracker(matcher, index, uidMap); + EXPECT_NE(tracker, nullptr); + + // Combination matchers need to be initialized first. + EXPECT_FALSE(tracker->mInitialized); + EXPECT_EQ(tracker->getId(), id); + EXPECT_EQ(tracker->mIndex, index); + const set<int>& atomIds = tracker->getAtomIds(); + ASSERT_EQ(atomIds.size(), 0); +} + +} // namespace statsd +} // namespace os +} // namespace android + +#else +GTEST_LOG_(INFO) << "This test does nothing.\n"; +#endif diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp index cee83725d075..0be983f2a9b0 100644 --- a/cmds/statsd/tests/statsd_test_util.cpp +++ b/cmds/statsd/tests/statsd_test_util.cpp @@ -15,6 +15,8 @@ #include "statsd_test_util.h" #include <aidl/android/util/StatsEventParcel.h> + +#include "matchers/SimpleLogMatchingTracker.h" #include "stats_event.h" using aidl::android::util::StatsEventParcel; @@ -996,6 +998,20 @@ int64_t StringToId(const string& str) { return static_cast<int64_t>(std::hash<std::string>()(str)); } +sp<EventMatcherWizard> createEventMatcherWizard( + int tagId, int matcherIndex, const vector<FieldValueMatcher>& fieldValueMatchers) { + sp<UidMap> uidMap = new UidMap(); + SimpleAtomMatcher atomMatcher; + atomMatcher.set_atom_id(tagId); + for (const FieldValueMatcher& fvm : fieldValueMatchers) { + *atomMatcher.add_field_value_matcher() = fvm; + } + uint64_t matcherHash = 0x12345678; + int64_t matcherId = 678; + return new EventMatcherWizard({new SimpleLogMatchingTracker(matcherId, matcherIndex, + matcherHash, atomMatcher, uidMap)}); +} + void ValidateWakelockAttributionUidAndTagDimension(const DimensionsValue& value, const int atomId, const int uid, const string& tag) { EXPECT_EQ(value.field(), atomId); diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h index 3dcf4ecce054..1220019e2353 100644 --- a/cmds/statsd/tests/statsd_test_util.h +++ b/cmds/statsd/tests/statsd_test_util.h @@ -25,6 +25,7 @@ #include "src/StatsLogProcessor.h" #include "src/hash.h" #include "src/logd/LogEvent.h" +#include "src/matchers/EventMatcherWizard.h" #include "src/packages/UidMap.h" #include "src/stats_log_util.h" #include "stats_event.h" @@ -335,6 +336,9 @@ void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events); int64_t StringToId(const string& str); +sp<EventMatcherWizard> createEventMatcherWizard( + int tagId, int matcherIndex, const std::vector<FieldValueMatcher>& fieldValueMatchers = {}); + void ValidateWakelockAttributionUidAndTagDimension(const DimensionsValue& value, const int atomId, const int uid, const string& tag); void ValidateUidDimension(const DimensionsValue& value, int node_idx, int atomId, int uid); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 522b8cc5a46f..5c4951e23ea2 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -3827,6 +3827,12 @@ public class Activity extends ContextThemeWrapper } catch (RemoteException e) { finishAfterTransition(); } + + // Activity was launched when user tapped a link in the Autofill Save UI - Save UI must + // be restored now. + if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)) { + restoreAutofillSaveUi(); + } } /** diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl index 8c3180b400ef..4c9e400681ee 100644 --- a/core/java/android/app/IUiAutomationConnection.aidl +++ b/core/java/android/app/IUiAutomationConnection.aidl @@ -39,7 +39,7 @@ interface IUiAutomationConnection { boolean injectInputEvent(in InputEvent event, boolean sync); void syncInputTransactions(); boolean setRotation(int rotation); - Bitmap takeScreenshot(in Rect crop, int rotation); + Bitmap takeScreenshot(in Rect crop); boolean clearWindowContentFrameStats(int windowId); WindowContentFrameStats getWindowContentFrameStats(int windowId); void clearWindowAnimationFrameStats(); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 68e65612971c..6f3e89229e4c 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -1492,6 +1492,7 @@ public class Notification implements Parcelable private boolean mAllowGeneratedReplies = true; private final @SemanticAction int mSemanticAction; private final boolean mIsContextual; + private boolean mAuthenticationRequired; /** * Small icon representing the action. @@ -1528,6 +1529,7 @@ public class Notification implements Parcelable mAllowGeneratedReplies = in.readInt() == 1; mSemanticAction = in.readInt(); mIsContextual = in.readInt() == 1; + mAuthenticationRequired = in.readInt() == 1; } /** @@ -1536,13 +1538,14 @@ public class Notification implements Parcelable @Deprecated public Action(int icon, CharSequence title, PendingIntent intent) { this(Icon.createWithResource("", icon), title, intent, new Bundle(), null, true, - SEMANTIC_ACTION_NONE, false /* isContextual */); + SEMANTIC_ACTION_NONE, false /* isContextual */, false /* requireAuth */); } /** Keep in sync with {@link Notification.Action.Builder#Builder(Action)}! */ private Action(Icon icon, CharSequence title, PendingIntent intent, Bundle extras, RemoteInput[] remoteInputs, boolean allowGeneratedReplies, - @SemanticAction int semanticAction, boolean isContextual) { + @SemanticAction int semanticAction, boolean isContextual, + boolean requireAuth) { this.mIcon = icon; if (icon != null && icon.getType() == Icon.TYPE_RESOURCE) { this.icon = icon.getResId(); @@ -1554,6 +1557,7 @@ public class Notification implements Parcelable this.mAllowGeneratedReplies = allowGeneratedReplies; this.mSemanticAction = semanticAction; this.mIsContextual = isContextual; + this.mAuthenticationRequired = requireAuth; } /** @@ -1624,6 +1628,17 @@ public class Notification implements Parcelable } /** + * Returns whether the OS should only send this action's {@link PendingIntent} on an + * unlocked device. + * + * If the device is locked when the action is invoked, the OS should show the keyguard and + * require successful authentication before invoking the intent. + */ + public boolean isAuthenticationRequired() { + return mAuthenticationRequired; + } + + /** * Builder class for {@link Action} objects. */ public static final class Builder { @@ -1635,6 +1650,7 @@ public class Notification implements Parcelable @Nullable private ArrayList<RemoteInput> mRemoteInputs; private @SemanticAction int mSemanticAction; private boolean mIsContextual; + private boolean mAuthenticationRequired; /** * Construct a new builder for {@link Action} object. @@ -1654,7 +1670,7 @@ public class Notification implements Parcelable * @param intent the {@link PendingIntent} to fire when users trigger this action */ public Builder(Icon icon, CharSequence title, PendingIntent intent) { - this(icon, title, intent, new Bundle(), null, true, SEMANTIC_ACTION_NONE); + this(icon, title, intent, new Bundle(), null, true, SEMANTIC_ACTION_NONE, false); } /** @@ -1665,23 +1681,25 @@ public class Notification implements Parcelable public Builder(Action action) { this(action.getIcon(), action.title, action.actionIntent, new Bundle(action.mExtras), action.getRemoteInputs(), - action.getAllowGeneratedReplies(), action.getSemanticAction()); + action.getAllowGeneratedReplies(), action.getSemanticAction(), + action.isAuthenticationRequired()); } private Builder(@Nullable Icon icon, @Nullable CharSequence title, @Nullable PendingIntent intent, @NonNull Bundle extras, @Nullable RemoteInput[] remoteInputs, boolean allowGeneratedReplies, - @SemanticAction int semanticAction) { + @SemanticAction int semanticAction, boolean authRequired) { mIcon = icon; mTitle = title; mIntent = intent; mExtras = extras; if (remoteInputs != null) { - mRemoteInputs = new ArrayList<RemoteInput>(remoteInputs.length); + mRemoteInputs = new ArrayList<>(remoteInputs.length); Collections.addAll(mRemoteInputs, remoteInputs); } mAllowGeneratedReplies = allowGeneratedReplies; mSemanticAction = semanticAction; + mAuthenticationRequired = authRequired; } /** @@ -1776,6 +1794,21 @@ public class Notification implements Parcelable } /** + * Sets whether the OS should only send this action's {@link PendingIntent} on an + * unlocked device. + * + * If this is true and the device is locked when the action is invoked, the OS will + * show the keyguard and require successful authentication before invoking the intent. + * If this is false and the device is locked, the OS will decide whether authentication + * should be required. + */ + @NonNull + public Builder setAuthenticationRequired(boolean authenticationRequired) { + mAuthenticationRequired = authenticationRequired; + return this; + } + + /** * Throws an NPE if we are building a contextual action missing one of the fields * necessary to display the action. */ @@ -1827,7 +1860,8 @@ public class Notification implements Parcelable RemoteInput[] textInputsArr = textInputs.isEmpty() ? null : textInputs.toArray(new RemoteInput[textInputs.size()]); return new Action(mIcon, mTitle, mIntent, mExtras, textInputsArr, - mAllowGeneratedReplies, mSemanticAction, mIsContextual); + mAllowGeneratedReplies, mSemanticAction, mIsContextual, + mAuthenticationRequired); } } @@ -1841,7 +1875,8 @@ public class Notification implements Parcelable getRemoteInputs(), getAllowGeneratedReplies(), getSemanticAction(), - isContextual()); + isContextual(), + isAuthenticationRequired()); } @Override @@ -1870,6 +1905,7 @@ public class Notification implements Parcelable out.writeInt(mAllowGeneratedReplies ? 1 : 0); out.writeInt(mSemanticAction); out.writeInt(mIsContextual ? 1 : 0); + out.writeInt(mAuthenticationRequired ? 1 : 0); } public static final @android.annotation.NonNull Parcelable.Creator<Action> CREATOR = diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java index e0951bf3f4d2..109205fadf18 100644 --- a/core/java/android/app/UiAutomation.java +++ b/core/java/android/app/UiAutomation.java @@ -903,7 +903,7 @@ public final class UiAutomation { try { // Calling out without a lock held. screenShot = mUiAutomationConnection.takeScreenshot( - new Rect(0, 0, displaySize.x, displaySize.y), rotation); + new Rect(0, 0, displaySize.x, displaySize.y)); if (screenShot == null) { return null; } diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java index ce51dba76780..70d520176ca1 100644 --- a/core/java/android/app/UiAutomationConnection.java +++ b/core/java/android/app/UiAutomationConnection.java @@ -180,7 +180,7 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub { } @Override - public Bitmap takeScreenshot(Rect crop, int rotation) { + public Bitmap takeScreenshot(Rect crop) { synchronized (mLock) { throwIfCalledByNotTrustedUidLocked(); throwIfShutdownLocked(); @@ -190,7 +190,15 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub { try { int width = crop.width(); int height = crop.height(); - return SurfaceControl.screenshot(crop, width, height, rotation); + final IBinder displayToken = SurfaceControl.getInternalDisplayToken(); + final SurfaceControl.DisplayCaptureArgs captureArgs = + new SurfaceControl.DisplayCaptureArgs.Builder(displayToken) + .setSourceCrop(crop) + .setSize(width, height) + .build(); + final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer = + SurfaceControl.captureDisplay(captureArgs); + return screenshotBuffer == null ? null : screenshotBuffer.asBitmap(); } finally { Binder.restoreCallingIdentity(identity); } diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java index 16ddcd1d0ea3..056cfc7c28f1 100644 --- a/core/java/android/app/backup/BackupAgent.java +++ b/core/java/android/app/backup/BackupAgent.java @@ -402,7 +402,7 @@ public abstract class BackupAgent extends ContextWrapper { */ public void onFullBackup(FullBackupDataOutput data) throws IOException { FullBackup.BackupScheme backupScheme = FullBackup.getBackupScheme(this); - if (!backupScheme.isFullBackupContentEnabled()) { + if (!isDeviceToDeviceMigration() && !backupScheme.isFullBackupContentEnabled()) { return; } @@ -430,24 +430,18 @@ public abstract class BackupAgent extends ContextWrapper { final Context ceContext = createCredentialProtectedStorageContext(); final String rootDir = ceContext.getDataDir().getCanonicalPath(); final String filesDir = ceContext.getFilesDir().getCanonicalPath(); - final String noBackupDir = ceContext.getNoBackupFilesDir().getCanonicalPath(); final String databaseDir = ceContext.getDatabasePath("foo").getParentFile() .getCanonicalPath(); final String sharedPrefsDir = ceContext.getSharedPreferencesPath("foo").getParentFile() .getCanonicalPath(); - final String cacheDir = ceContext.getCacheDir().getCanonicalPath(); - final String codeCacheDir = ceContext.getCodeCacheDir().getCanonicalPath(); final Context deContext = createDeviceProtectedStorageContext(); final String deviceRootDir = deContext.getDataDir().getCanonicalPath(); final String deviceFilesDir = deContext.getFilesDir().getCanonicalPath(); - final String deviceNoBackupDir = deContext.getNoBackupFilesDir().getCanonicalPath(); final String deviceDatabaseDir = deContext.getDatabasePath("foo").getParentFile() .getCanonicalPath(); final String deviceSharedPrefsDir = deContext.getSharedPreferencesPath("foo") .getParentFile().getCanonicalPath(); - final String deviceCacheDir = deContext.getCacheDir().getCanonicalPath(); - final String deviceCodeCacheDir = deContext.getCodeCacheDir().getCanonicalPath(); final String libDir = (appInfo.nativeLibraryDir != null) ? new File(appInfo.nativeLibraryDir).getCanonicalPath() @@ -460,33 +454,36 @@ public abstract class BackupAgent extends ContextWrapper { // Add the directories we always exclude. traversalExcludeSet.add(filesDir); - traversalExcludeSet.add(noBackupDir); traversalExcludeSet.add(databaseDir); traversalExcludeSet.add(sharedPrefsDir); - traversalExcludeSet.add(cacheDir); - traversalExcludeSet.add(codeCacheDir); traversalExcludeSet.add(deviceFilesDir); - traversalExcludeSet.add(deviceNoBackupDir); traversalExcludeSet.add(deviceDatabaseDir); traversalExcludeSet.add(deviceSharedPrefsDir); - traversalExcludeSet.add(deviceCacheDir); - traversalExcludeSet.add(deviceCodeCacheDir); if (libDir != null) { traversalExcludeSet.add(libDir); } + Set<String> extraExcludedDirs = getExtraExcludeDirsIfAny(ceContext); + Set<String> extraExcludedDeviceDirs = getExtraExcludeDirsIfAny(deContext); + traversalExcludeSet.addAll(extraExcludedDirs); + traversalExcludeSet.addAll(extraExcludedDeviceDirs); + // Root dir first. applyXmlFiltersAndDoFullBackupForDomain( packageName, FullBackup.ROOT_TREE_TOKEN, manifestIncludeMap, manifestExcludeSet, traversalExcludeSet, data); traversalExcludeSet.add(rootDir); + // Exclude the extra directories anyway, since we've already covered them if it was needed. + traversalExcludeSet.addAll(extraExcludedDirs); applyXmlFiltersAndDoFullBackupForDomain( packageName, FullBackup.DEVICE_ROOT_TREE_TOKEN, manifestIncludeMap, manifestExcludeSet, traversalExcludeSet, data); traversalExcludeSet.add(deviceRootDir); + // Exclude the extra directories anyway, since we've already covered them if it was needed. + traversalExcludeSet.addAll(extraExcludedDeviceDirs); // Data dir next. traversalExcludeSet.remove(filesDir); @@ -545,11 +542,28 @@ public abstract class BackupAgent extends ContextWrapper { } } + private Set<String> getExtraExcludeDirsIfAny(Context context) throws IOException { + if (isDeviceToDeviceMigration()) { + return Collections.emptySet(); + } + + // If this is not a migration, also exclude no-backup and cache dirs. + Set<String> excludedDirs = new HashSet<>(); + excludedDirs.add(context.getCacheDir().getCanonicalPath()); + excludedDirs.add(context.getCodeCacheDir().getCanonicalPath()); + excludedDirs.add(context.getNoBackupFilesDir().getCanonicalPath()); + return Collections.unmodifiableSet(excludedDirs); + } + + private boolean isDeviceToDeviceMigration() { + return mOperationType == OperationType.MIGRATION; + } + /** @hide */ @VisibleForTesting public IncludeExcludeRules getIncludeExcludeRules(FullBackup.BackupScheme backupScheme) throws IOException, XmlPullParserException { - if (mOperationType == OperationType.MIGRATION) { + if (isDeviceToDeviceMigration()) { return IncludeExcludeRules.emptyRules(); } @@ -892,6 +906,11 @@ public abstract class BackupAgent extends ContextWrapper { } private boolean isFileEligibleForRestore(File destination) throws IOException { + if (isDeviceToDeviceMigration()) { + // Everything is eligible for device-to-device migration. + return true; + } + FullBackup.BackupScheme bs = FullBackup.getBackupScheme(this); if (!bs.isFullBackupContentEnabled()) { if (Log.isLoggable(FullBackup.TAG_XML_PARSER, Log.VERBOSE)) { diff --git a/core/java/android/app/timezonedetector/TimeZoneCapabilities.java b/core/java/android/app/timezonedetector/TimeZoneCapabilities.java index 236b0064763e..cc0af3f97e49 100644 --- a/core/java/android/app/timezonedetector/TimeZoneCapabilities.java +++ b/core/java/android/app/timezonedetector/TimeZoneCapabilities.java @@ -91,11 +91,13 @@ public final class TimeZoneCapabilities implements Parcelable { private final @UserIdInt int mUserId; private final @CapabilityState int mConfigureAutoDetectionEnabled; + private final @CapabilityState int mConfigureGeoDetectionEnabled; private final @CapabilityState int mSuggestManualTimeZone; private TimeZoneCapabilities(@NonNull Builder builder) { this.mUserId = builder.mUserId; this.mConfigureAutoDetectionEnabled = builder.mConfigureAutoDetectionEnabled; + this.mConfigureGeoDetectionEnabled = builder.mConfigureGeoDetectionEnabled; this.mSuggestManualTimeZone = builder.mSuggestManualTimeZone; } @@ -103,6 +105,7 @@ public final class TimeZoneCapabilities implements Parcelable { private static TimeZoneCapabilities createFromParcel(Parcel in) { return new TimeZoneCapabilities.Builder(in.readInt()) .setConfigureAutoDetectionEnabled(in.readInt()) + .setConfigureGeoDetectionEnabled(in.readInt()) .setSuggestManualTimeZone(in.readInt()) .build(); } @@ -111,6 +114,7 @@ public final class TimeZoneCapabilities implements Parcelable { public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mUserId); dest.writeInt(mConfigureAutoDetectionEnabled); + dest.writeInt(mConfigureGeoDetectionEnabled); dest.writeInt(mSuggestManualTimeZone); } @@ -120,8 +124,8 @@ public final class TimeZoneCapabilities implements Parcelable { } /** - * Returns the user's capability state for controlling automatic time zone detection via - * {@link TimeZoneDetector#updateConfiguration(TimeZoneConfiguration)} and {@link + * Returns the user's capability state for controlling whether automatic time zone detection is + * enabled via {@link TimeZoneDetector#updateConfiguration(TimeZoneConfiguration)} and {@link * TimeZoneConfiguration#isAutoDetectionEnabled()}. */ @CapabilityState @@ -130,6 +134,16 @@ public final class TimeZoneCapabilities implements Parcelable { } /** + * Returns the user's capability state for controlling whether geolocation can be used to detect + * time zone via {@link TimeZoneDetector#updateConfiguration(TimeZoneConfiguration)} and {@link + * TimeZoneConfiguration#isGeoDetectionEnabled()}. + */ + @CapabilityState + public int getConfigureGeoDetectionEnabled() { + return mConfigureGeoDetectionEnabled; + } + + /** * Returns the user's capability state for manually setting the time zone on a device via * {@link TimeZoneDetector#suggestManualTimeZone(ManualTimeZoneSuggestion)}. * @@ -157,12 +171,16 @@ public final class TimeZoneCapabilities implements Parcelable { TimeZoneCapabilities that = (TimeZoneCapabilities) o; return mUserId == that.mUserId && mConfigureAutoDetectionEnabled == that.mConfigureAutoDetectionEnabled + && mConfigureGeoDetectionEnabled == that.mConfigureGeoDetectionEnabled && mSuggestManualTimeZone == that.mSuggestManualTimeZone; } @Override public int hashCode() { - return Objects.hash(mUserId, mConfigureAutoDetectionEnabled, mSuggestManualTimeZone); + return Objects.hash(mUserId, + mConfigureAutoDetectionEnabled, + mConfigureGeoDetectionEnabled, + mSuggestManualTimeZone); } @Override @@ -170,6 +188,7 @@ public final class TimeZoneCapabilities implements Parcelable { return "TimeZoneDetectorCapabilities{" + "mUserId=" + mUserId + ", mConfigureAutomaticDetectionEnabled=" + mConfigureAutoDetectionEnabled + + ", mConfigureGeoDetectionEnabled=" + mConfigureGeoDetectionEnabled + ", mSuggestManualTimeZone=" + mSuggestManualTimeZone + '}'; } @@ -179,6 +198,7 @@ public final class TimeZoneCapabilities implements Parcelable { private final @UserIdInt int mUserId; private @CapabilityState int mConfigureAutoDetectionEnabled; + private @CapabilityState int mConfigureGeoDetectionEnabled; private @CapabilityState int mSuggestManualTimeZone; /** @@ -194,6 +214,12 @@ public final class TimeZoneCapabilities implements Parcelable { return this; } + /** Sets the state for the geolocation time zone detection enabled config. */ + public Builder setConfigureGeoDetectionEnabled(@CapabilityState int value) { + this.mConfigureGeoDetectionEnabled = value; + return this; + } + /** Sets the state for the suggestManualTimeZone action. */ public Builder setSuggestManualTimeZone(@CapabilityState int value) { this.mSuggestManualTimeZone = value; @@ -204,6 +230,7 @@ public final class TimeZoneCapabilities implements Parcelable { @NonNull public TimeZoneCapabilities build() { verifyCapabilitySet(mConfigureAutoDetectionEnabled, "configureAutoDetectionEnabled"); + verifyCapabilitySet(mConfigureGeoDetectionEnabled, "configureGeoDetectionEnabled"); verifyCapabilitySet(mSuggestManualTimeZone, "suggestManualTimeZone"); return new TimeZoneCapabilities(this); } diff --git a/core/java/android/app/timezonedetector/TimeZoneConfiguration.java b/core/java/android/app/timezonedetector/TimeZoneConfiguration.java index 047d3493d5dd..6f84ee22a985 100644 --- a/core/java/android/app/timezonedetector/TimeZoneConfiguration.java +++ b/core/java/android/app/timezonedetector/TimeZoneConfiguration.java @@ -67,6 +67,10 @@ public final class TimeZoneConfiguration implements Parcelable { @Property public static final String PROPERTY_AUTO_DETECTION_ENABLED = "autoDetectionEnabled"; + /** See {@link TimeZoneConfiguration#isGeoDetectionEnabled()} for details. */ + @Property + public static final String PROPERTY_GEO_DETECTION_ENABLED = "geoDetectionEnabled"; + private final Bundle mBundle; private TimeZoneConfiguration(Builder builder) { @@ -86,7 +90,8 @@ public final class TimeZoneConfiguration implements Parcelable { /** Returns {@code true} if all known properties are set. */ public boolean isComplete() { - return hasProperty(PROPERTY_AUTO_DETECTION_ENABLED); + return hasProperty(PROPERTY_AUTO_DETECTION_ENABLED) + && hasProperty(PROPERTY_GEO_DETECTION_ENABLED); } /** Returns true if the specified property is set. */ @@ -108,6 +113,28 @@ public final class TimeZoneConfiguration implements Parcelable { return mBundle.getBoolean(PROPERTY_AUTO_DETECTION_ENABLED); } + /** + * Returns the value of the {@link #PROPERTY_GEO_DETECTION_ENABLED} property. This + * controls whether a device can use location to determine time zone. Only used when + * {@link #isAutoDetectionEnabled()} is true. + * + * @throws IllegalStateException if the field has not been set + */ + public boolean isGeoDetectionEnabled() { + if (!mBundle.containsKey(PROPERTY_GEO_DETECTION_ENABLED)) { + throw new IllegalStateException(PROPERTY_GEO_DETECTION_ENABLED + " is not set"); + } + return mBundle.getBoolean(PROPERTY_GEO_DETECTION_ENABLED); + } + + /** + * Convenience method to merge this with another. The argument configuration properties have + * precedence. + */ + public TimeZoneConfiguration with(TimeZoneConfiguration other) { + return new Builder(this).mergeProperties(other).build(); + } + @Override public int describeContents() { return 0; @@ -174,6 +201,12 @@ public final class TimeZoneConfiguration implements Parcelable { return this; } + /** Sets the desired state of the geolocation time zone detection enabled property. */ + public Builder setGeoDetectionEnabled(boolean enabled) { + this.mBundle.putBoolean(PROPERTY_GEO_DETECTION_ENABLED, enabled); + return this; + } + /** Returns the {@link TimeZoneConfiguration}. */ @NonNull public TimeZoneConfiguration build() { diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java index 3522b1b8aff5..0e6a0637d801 100644 --- a/core/java/android/app/usage/UsageEvents.java +++ b/core/java/android/app/usage/UsageEvents.java @@ -199,7 +199,7 @@ public final class UsageEvents implements Parcelable { public static final int NOTIFICATION_INTERRUPTION = 12; /** - * A Slice was pinned by the default launcher or the default assistant. + * A Slice was pinned by the default assistant. * @hide */ @SystemApi diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java index 3d3759e695e0..f14f66b07630 100644 --- a/core/java/android/os/Parcelable.java +++ b/core/java/android/os/Parcelable.java @@ -161,6 +161,7 @@ public interface Parcelable { * @return true if this parcelable is stable. * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) default @Stability int getStability() { return PARCELABLE_STABILITY_LOCAL; } diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java index fd68c2b9b5fd..26f3af0c68bb 100644 --- a/core/java/android/os/SystemClock.java +++ b/core/java/android/os/SystemClock.java @@ -178,6 +178,15 @@ public final class SystemClock { native public static long uptimeMillis(); /** + * Returns nanoseconds since boot, not counting time spent in deep sleep. + * + * @return nanoseconds of non-sleep uptime since boot. + * @hide + */ + @CriticalNative + public static native long uptimeNanos(); + + /** * Return {@link Clock} that starts at system boot, not counting time spent * in deep sleep. * diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 2ce993dfedca..6ef086b55c41 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -22,8 +22,6 @@ import static android.graphics.Matrix.MSKEW_X; import static android.graphics.Matrix.MSKEW_Y; import static android.graphics.Matrix.MTRANS_X; import static android.graphics.Matrix.MTRANS_Y; -import static android.view.Surface.ROTATION_270; -import static android.view.Surface.ROTATION_90; import static android.view.SurfaceControlProto.HASH_CODE; import static android.view.SurfaceControlProto.NAME; @@ -590,6 +588,26 @@ public final class SurfaceControl implements Parcelable { public boolean containsSecureLayers() { return mContainsSecureLayers; } + + /** + * Copy content of ScreenshotHardwareBuffer into a hardware bitmap and return it. + * Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap + * into + * a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)} + * + * CAVEAT: This can be extremely slow; avoid use unless absolutely necessary; prefer to + * directly + * use the {@link HardwareBuffer} directly. + * + * @return Bitmap generated from the {@link HardwareBuffer} + */ + public Bitmap asBitmap() { + if (mHardwareBuffer == null) { + Log.w(TAG, "Failed to take screenshot. Null screenshot object"); + return null; + } + return Bitmap.wrapHardwareBuffer(mHardwareBuffer, mColorSpace); + } } /** @@ -597,7 +615,7 @@ public final class SurfaceControl implements Parcelable { * are shared between {@link DisplayCaptureArgs} and {@link LayerCaptureArgs} * @hide */ - public abstract static class CaptureArgs { + private abstract static class CaptureArgs { private final int mPixelFormat; private final Rect mSourceCrop = new Rect(); private final float mFrameScale; @@ -615,7 +633,7 @@ public final class SurfaceControl implements Parcelable { * * @param <T> A builder that extends {@link Builder} */ - public abstract static class Builder<T extends Builder<T>> { + abstract static class Builder<T extends Builder<T>> { private int mPixelFormat = PixelFormat.RGBA_8888; private final Rect mSourceCrop = new Rect(); private float mFrameScale = 1; @@ -675,7 +693,6 @@ public final class SurfaceControl implements Parcelable { private final int mWidth; private final int mHeight; private final boolean mUseIdentityTransform; - private final int mRotation; private DisplayCaptureArgs(Builder builder) { super(builder); @@ -683,7 +700,6 @@ public final class SurfaceControl implements Parcelable { mWidth = builder.mWidth; mHeight = builder.mHeight; mUseIdentityTransform = builder.mUseIdentityTransform; - mRotation = builder.mRotation; } /** @@ -694,7 +710,6 @@ public final class SurfaceControl implements Parcelable { private int mWidth; private int mHeight; private boolean mUseIdentityTransform; - private @Surface.Rotation int mRotation = Surface.ROTATION_0; /** * Construct a new {@link LayerCaptureArgs} with the set parameters. The builder @@ -736,26 +751,16 @@ public final class SurfaceControl implements Parcelable { } /** - * Replace whatever transformation (rotation, scaling, translation) the surface - * layers are currently using with the identity transformation while taking the - * screenshot. + * Replace the rotation transform of the display with the identity transformation while + * taking the screenshot. This ensures the screenshot is taken in the ROTATION_0 + * orientation. Set this value to false if the screenshot should be taken in the + * current screen orientation. */ public Builder setUseIdentityTransform(boolean useIdentityTransform) { mUseIdentityTransform = useIdentityTransform; return this; } - /** - * Apply a custom clockwise rotation to the screenshot, i.e. - * Surface.ROTATION_0,90,180,270. SurfaceFlinger will always take screenshots in its - * native portrait orientation by default, so this is useful for returning screenshots - * that are independent of device orientation. - */ - public Builder setRotation(@Surface.Rotation int rotation) { - mRotation = rotation; - return this; - } - @Override Builder getThis() { return this; @@ -2221,130 +2226,16 @@ public final class SurfaceControl implements Parcelable { } /** - * @see SurfaceControl#screenshot(Rect, int, int, boolean, int)} - * @hide - */ - @UnsupportedAppUsage - public static Bitmap screenshot(Rect sourceCrop, int width, int height, int rotation) { - return screenshot(sourceCrop, width, height, false, rotation); - } - - /** - * Copy the current screen contents into a hardware bitmap and return it. - * Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap into - * a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)} + * Captures all the surfaces in a display and returns a {@link ScreenshotHardwareBuffer} with + * the content. * - * CAVEAT: Versions of screenshot that return a {@link Bitmap} can be extremely slow; avoid use - * unless absolutely necessary; prefer the versions that use a {@link HardwareBuffer} such as - * {@link SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)}. - * - * @see SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)} * @hide */ - @UnsupportedAppUsage - public static Bitmap screenshot(Rect sourceCrop, int width, int height, - boolean useIdentityTransform, int rotation) { - // TODO: should take the display as a parameter - final IBinder displayToken = SurfaceControl.getInternalDisplayToken(); - if (displayToken == null) { - Log.w(TAG, "Failed to take screenshot because internal display is disconnected"); - return null; - } - - if (rotation == ROTATION_90 || rotation == ROTATION_270) { - rotation = (rotation == ROTATION_90) ? ROTATION_270 : ROTATION_90; - } - - SurfaceControl.rotateCropForSF(sourceCrop, rotation); - final ScreenshotHardwareBuffer buffer = screenshotToBuffer(displayToken, sourceCrop, width, - height, useIdentityTransform, rotation); - - if (buffer == null) { - Log.w(TAG, "Failed to take screenshot"); - return null; - } - return Bitmap.wrapHardwareBuffer(buffer.getHardwareBuffer(), buffer.getColorSpace()); - } - - /** - * Captures all the surfaces in a display and returns a {@link HardwareBuffer} with the content. - * - * @param display The display to take the screenshot of. - * @param sourceCrop The portion of the screen to capture into the Bitmap; caller may - * pass in 'new Rect()' if no cropping is desired. - * @param width The desired width of the returned bitmap; the raw screen will be - * scaled down to this size; caller may pass in 0 if no scaling is - * desired. - * @param height The desired height of the returned bitmap; the raw screen will - * be scaled down to this size; caller may pass in 0 if no scaling - * is desired. - * @param useIdentityTransform Replace whatever transformation (rotation, scaling, translation) - * the surface layers are currently using with the identity - * transformation while taking the screenshot. - * @param rotation Apply a custom clockwise rotation to the screenshot, i.e. - * Surface.ROTATION_0,90,180,270. SurfaceFlinger will always take - * screenshots in its native portrait orientation by default, so - * this is useful for returning screenshots that are independent of - * device orientation. - * @return Returns a HardwareBuffer that contains the captured content. - * @hide - */ - public static ScreenshotHardwareBuffer screenshotToBuffer(IBinder display, Rect sourceCrop, - int width, int height, boolean useIdentityTransform, int rotation) { - if (display == null) { - throw new IllegalArgumentException("displayToken must not be null"); - } - - DisplayCaptureArgs captureArgs = new DisplayCaptureArgs.Builder(display) - .setSourceCrop(sourceCrop) - .setSize(width, height) - .setUseIdentityTransform(useIdentityTransform) - .setRotation(rotation) - .build(); - + public static ScreenshotHardwareBuffer captureDisplay(DisplayCaptureArgs captureArgs) { return nativeCaptureDisplay(captureArgs); } /** - * Like screenshotToBuffer, but if the caller is AID_SYSTEM, allows - * for the capture of secure layers. This is used for the screen rotation - * animation where the system server takes screenshots but does - * not persist them or allow them to leave the server. However in other - * cases in the system server, we mostly want to omit secure layers - * like when we take a screenshot on behalf of the assistant. - * - * @hide - */ - public static ScreenshotHardwareBuffer screenshotToBufferWithSecureLayersUnsafe(IBinder display, - Rect sourceCrop, int width, int height, boolean useIdentityTransform, - int rotation) { - if (display == null) { - throw new IllegalArgumentException("displayToken must not be null"); - } - - DisplayCaptureArgs captureArgs = new DisplayCaptureArgs.Builder(display) - .setSourceCrop(sourceCrop) - .setSize(width, height) - .setUseIdentityTransform(useIdentityTransform) - .setRotation(rotation) - .setCaptureSecureLayers(true) - .build(); - - return nativeCaptureDisplay(captureArgs); - } - - private static void rotateCropForSF(Rect crop, int rot) { - if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { - int tmp = crop.top; - crop.top = crop.left; - crop.left = tmp; - tmp = crop.right; - crop.right = crop.bottom; - crop.bottom = tmp; - } - } - - /** * Captures a layer and its children and returns a {@link HardwareBuffer} with the content. * * @param layer The root layer to capture. diff --git a/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl b/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl index e814ec649087..eb67191e5f54 100644 --- a/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl +++ b/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl @@ -29,7 +29,7 @@ import android.view.accessibility.IWindowMagnificationConnectionCallback; oneway interface IWindowMagnificationConnection { /** - * Enables window magnification on specifed display with specified center and scale. + * Enables window magnification on specified display with given center and scale and animation. * * @param displayId The logical display id. * @param scale magnification scale. @@ -41,7 +41,7 @@ oneway interface IWindowMagnificationConnection { void enableWindowMagnification(int displayId, float scale, float centerX, float centerY); /** - * Sets the scale of the window magnifier on specifed display. + * Sets the scale of the window magnifier on specified display. * * @param displayId The logical display id. * @param scale magnification scale. @@ -49,14 +49,14 @@ oneway interface IWindowMagnificationConnection { void setScale(int displayId, float scale); /** - * Disables window magnification on specifed display. + * Disables window magnification on specified display with animation. * * @param displayId The logical display id. */ void disableWindowMagnification(int displayId); /** - * Moves the window magnifier on the specifed display. + * Moves the window magnifier on the specified display. It has no effect while animating. * * @param offsetX the amount in pixels to offset the window magnifier in the X direction, in * current screen pixels. diff --git a/core/java/android/view/textclassifier/TextClassificationSession.java b/core/java/android/view/textclassifier/TextClassificationSession.java index fed3dbf8f49c..00086587819f 100644 --- a/core/java/android/view/textclassifier/TextClassificationSession.java +++ b/core/java/android/view/textclassifier/TextClassificationSession.java @@ -20,9 +20,11 @@ import android.annotation.NonNull; import android.annotation.WorkerThread; import android.view.textclassifier.SelectionEvent.InvocationMethod; +import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; import java.util.Objects; +import java.util.function.Supplier; import sun.misc.Cleaner; @@ -40,6 +42,9 @@ final class TextClassificationSession implements TextClassifier { private final TextClassificationContext mClassificationContext; private final Cleaner mCleaner; + private final Object mLock = new Object(); + + @GuardedBy("mLock") private boolean mDestroyed; TextClassificationSession(TextClassificationContext context, TextClassifier delegate) { @@ -54,8 +59,7 @@ final class TextClassificationSession implements TextClassifier { @Override public TextSelection suggestSelection(TextSelection.Request request) { - checkDestroyed(); - return mDelegate.suggestSelection(request); + return checkDestroyedAndRun(() -> mDelegate.suggestSelection(request)); } private void initializeRemoteSession() { @@ -67,77 +71,97 @@ final class TextClassificationSession implements TextClassifier { @Override public TextClassification classifyText(TextClassification.Request request) { - checkDestroyed(); - return mDelegate.classifyText(request); + return checkDestroyedAndRun(() -> mDelegate.classifyText(request)); } @Override public TextLinks generateLinks(TextLinks.Request request) { - checkDestroyed(); - return mDelegate.generateLinks(request); + return checkDestroyedAndRun(() -> mDelegate.generateLinks(request)); } @Override public ConversationActions suggestConversationActions(ConversationActions.Request request) { - checkDestroyed(); - return mDelegate.suggestConversationActions(request); + return checkDestroyedAndRun(() -> mDelegate.suggestConversationActions(request)); } @Override public TextLanguage detectLanguage(TextLanguage.Request request) { - checkDestroyed(); - return mDelegate.detectLanguage(request); + return checkDestroyedAndRun(() -> mDelegate.detectLanguage(request)); } @Override public int getMaxGenerateLinksTextLength() { - checkDestroyed(); - return mDelegate.getMaxGenerateLinksTextLength(); + return checkDestroyedAndRun(mDelegate::getMaxGenerateLinksTextLength); } @Override public void onSelectionEvent(SelectionEvent event) { - try { - if (mEventHelper.sanitizeEvent(event)) { - mDelegate.onSelectionEvent(event); + checkDestroyedAndRun(() -> { + try { + if (mEventHelper.sanitizeEvent(event)) { + mDelegate.onSelectionEvent(event); + } + } catch (Exception e) { + // Avoid crashing for event reporting. + Log.e(LOG_TAG, "Error reporting text classifier selection event", e); } - } catch (Exception e) { - // Avoid crashing for event reporting. - Log.e(LOG_TAG, "Error reporting text classifier selection event", e); - } + return null; + }); } @Override public void onTextClassifierEvent(TextClassifierEvent event) { - try { - event.mHiddenTempSessionId = mSessionId; - mDelegate.onTextClassifierEvent(event); - } catch (Exception e) { - // Avoid crashing for event reporting. - Log.e(LOG_TAG, "Error reporting text classifier event", e); - } + checkDestroyedAndRun(() -> { + try { + event.mHiddenTempSessionId = mSessionId; + mDelegate.onTextClassifierEvent(event); + } catch (Exception e) { + // Avoid crashing for event reporting. + Log.e(LOG_TAG, "Error reporting text classifier event", e); + } + return null; + }); } @Override public void destroy() { - mCleaner.clean(); - mDestroyed = true; + synchronized (mLock) { + if (!mDestroyed) { + mCleaner.clean(); + mDestroyed = true; + } + } } @Override public boolean isDestroyed() { - return mDestroyed; + synchronized (mLock) { + return mDestroyed; + } } /** - * @throws IllegalStateException if this TextClassification session has been destroyed. + * Check whether the TextClassification Session was destroyed before and after the actual API + * invocation, and return response if not. + * + * @param responseSupplier a Supplier that represents a TextClassifier call + * @return the response of the TextClassifier call + * @throws IllegalStateException if this TextClassification session was destroyed before the + * call returned * @see #isDestroyed() * @see #destroy() */ - private void checkDestroyed() { - if (mDestroyed) { - throw new IllegalStateException("This TextClassification session has been destroyed"); + private <T> T checkDestroyedAndRun(Supplier<T> responseSupplier) { + if (!isDestroyed()) { + T response = responseSupplier.get(); + synchronized (mLock) { + if (!mDestroyed) { + return response; + } + } } + throw new IllegalStateException( + "This TextClassification session has been destroyed"); } /** diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java index 201626abd820..f5bef0b006f5 100644 --- a/core/java/com/android/internal/os/BinderCallsStats.java +++ b/core/java/com/android/internal/os/BinderCallsStats.java @@ -74,6 +74,10 @@ public class BinderCallsStats implements BinderInternal.Observer { // Whether to collect all the data: cpu + exceptions + reply/request sizes. private boolean mDetailedTracking = DETAILED_TRACKING_DEFAULT; + // If set to true, indicates that all transactions for specific UIDs are being + // recorded, ignoring sampling. The UidEntry.recordAllTransactions flag is also set + // for the UIDs being tracked. + private boolean mRecordingAllTransactionsForUid; // Sampling period to control how often to track CPU usage. 1 means all calls, 100 means ~1 out // of 100 requests. private int mPeriodicSamplingInterval = PERIODIC_SAMPLING_INTERVAL_DEFAULT; @@ -178,7 +182,8 @@ public class BinderCallsStats implements BinderInternal.Observer { @Override @Nullable public CallSession callStarted(Binder binder, int code, int workSourceUid) { - if (mDeviceState == null || mDeviceState.isCharging()) { + if (!mRecordingAllTransactionsForUid + && (mDeviceState == null || mDeviceState.isCharging())) { return null; } @@ -190,7 +195,9 @@ public class BinderCallsStats implements BinderInternal.Observer { s.exceptionThrown = false; s.cpuTimeStarted = -1; s.timeStarted = -1; - if (shouldRecordDetailedData()) { + s.recordedCall = shouldRecordDetailedData(); + + if (mRecordingAllTransactionsForUid || s.recordedCall) { s.cpuTimeStarted = getThreadTimeMicro(); s.timeStarted = getElapsedRealtimeMicro(); } @@ -218,8 +225,17 @@ public class BinderCallsStats implements BinderInternal.Observer { private void processCallEnded(CallSession s, int parcelRequestSize, int parcelReplySize, int workSourceUid) { - // Non-negative time signals we need to record data for this call. - final boolean recordCall = s.cpuTimeStarted >= 0; + UidEntry uidEntry = null; + final boolean recordCall; + if (s.recordedCall) { + recordCall = true; + } else if (mRecordingAllTransactionsForUid) { + uidEntry = getUidEntry(workSourceUid); + recordCall = uidEntry.recordAllTransactions; + } else { + recordCall = false; + } + final long duration; final long latencyDuration; if (recordCall) { @@ -238,14 +254,17 @@ public class BinderCallsStats implements BinderInternal.Observer { synchronized (mLock) { // This was already checked in #callStart but check again while synchronized. - if (mDeviceState == null || mDeviceState.isCharging()) { + if (!mRecordingAllTransactionsForUid + && (mDeviceState == null || mDeviceState.isCharging())) { return; } - final UidEntry uidEntry = getUidEntry(workSourceUid); + if (uidEntry == null) { + uidEntry = getUidEntry(workSourceUid); + } + uidEntry.callCount++; uidEntry.incrementalCallCount++; - if (recordCall) { uidEntry.cpuTimeMicros += duration; uidEntry.recordedCallCount++; @@ -357,28 +376,67 @@ public class BinderCallsStats implements BinderInternal.Observer { for (int entryIdx = 0; entryIdx < uidEntriesSize; entryIdx++) { final UidEntry entry = mUidEntries.valueAt(entryIdx); for (CallStat stat : entry.getCallStatsList()) { - ExportedCallStat exported = new ExportedCallStat(); - exported.workSourceUid = entry.workSourceUid; - exported.callingUid = stat.callingUid; - exported.className = stat.binderClass.getName(); - exported.binderClass = stat.binderClass; - exported.transactionCode = stat.transactionCode; - exported.screenInteractive = stat.screenInteractive; - exported.cpuTimeMicros = stat.cpuTimeMicros; - exported.maxCpuTimeMicros = stat.maxCpuTimeMicros; - exported.latencyMicros = stat.latencyMicros; - exported.maxLatencyMicros = stat.maxLatencyMicros; - exported.recordedCallCount = stat.recordedCallCount; - exported.callCount = stat.callCount; - exported.maxRequestSizeBytes = stat.maxRequestSizeBytes; - exported.maxReplySizeBytes = stat.maxReplySizeBytes; - exported.exceptionCount = stat.exceptionCount; - resultCallStats.add(exported); + resultCallStats.add(getExportedCallStat(entry.workSourceUid, stat)); } } } // Resolve codes outside of the lock since it can be slow. + resolveBinderMethodNames(resultCallStats); + + // Debug entries added to help validate the data. + if (mAddDebugEntries && mBatteryStopwatch != null) { + resultCallStats.add(createDebugEntry("start_time_millis", mStartElapsedTime)); + resultCallStats.add(createDebugEntry("end_time_millis", SystemClock.elapsedRealtime())); + resultCallStats.add( + createDebugEntry("battery_time_millis", mBatteryStopwatch.getMillis())); + resultCallStats.add(createDebugEntry("sampling_interval", mPeriodicSamplingInterval)); + } + + return resultCallStats; + } + + /** + * This method is expensive to call. + */ + public ArrayList<ExportedCallStat> getExportedCallStats(int workSourceUid) { + ArrayList<ExportedCallStat> resultCallStats = new ArrayList<>(); + synchronized (mLock) { + final UidEntry entry = getUidEntry(workSourceUid); + for (CallStat stat : entry.getCallStatsList()) { + resultCallStats.add(getExportedCallStat(workSourceUid, stat)); + } + } + + // Resolve codes outside of the lock since it can be slow. + resolveBinderMethodNames(resultCallStats); + + return resultCallStats; + } + + private ExportedCallStat getExportedCallStat(int workSourceUid, CallStat stat) { + ExportedCallStat exported = new ExportedCallStat(); + exported.workSourceUid = workSourceUid; + exported.callingUid = stat.callingUid; + exported.className = stat.binderClass.getName(); + exported.binderClass = stat.binderClass; + exported.transactionCode = stat.transactionCode; + exported.screenInteractive = stat.screenInteractive; + exported.cpuTimeMicros = stat.cpuTimeMicros; + exported.maxCpuTimeMicros = stat.maxCpuTimeMicros; + exported.latencyMicros = stat.latencyMicros; + exported.maxLatencyMicros = stat.maxLatencyMicros; + exported.recordedCallCount = stat.recordedCallCount; + exported.callCount = stat.callCount; + exported.maxRequestSizeBytes = stat.maxRequestSizeBytes; + exported.maxReplySizeBytes = stat.maxReplySizeBytes; + exported.exceptionCount = stat.exceptionCount; + return exported; + } + + private void resolveBinderMethodNames( + ArrayList<ExportedCallStat> resultCallStats) { + // Resolve codes outside of the lock since it can be slow. ExportedCallStat previous = null; String previousMethodName = null; resultCallStats.sort(BinderCallsStats::compareByBinderClassAndCode); @@ -398,17 +456,6 @@ public class BinderCallsStats implements BinderInternal.Observer { exported.methodName = methodName; previous = exported; } - - // Debug entries added to help validate the data. - if (mAddDebugEntries && mBatteryStopwatch != null) { - resultCallStats.add(createDebugEntry("start_time_millis", mStartElapsedTime)); - resultCallStats.add(createDebugEntry("end_time_millis", SystemClock.elapsedRealtime())); - resultCallStats.add( - createDebugEntry("battery_time_millis", mBatteryStopwatch.getMillis())); - resultCallStats.add(createDebugEntry("sampling_interval", mPeriodicSamplingInterval)); - } - - return resultCallStats; } private ExportedCallStat createDebugEntry(String variableName, long value) { @@ -432,33 +479,24 @@ public class BinderCallsStats implements BinderInternal.Observer { } /** Writes the collected statistics to the supplied {@link PrintWriter}.*/ - public void dump(PrintWriter pw, AppIdToPackageMap packageMap, boolean verbose) { + public void dump(PrintWriter pw, AppIdToPackageMap packageMap, int workSourceUid, + boolean verbose) { synchronized (mLock) { - dumpLocked(pw, packageMap, verbose); + dumpLocked(pw, packageMap, workSourceUid, verbose); } } - private void dumpLocked(PrintWriter pw, AppIdToPackageMap packageMap, boolean verbose) { - long totalCallsCount = 0; - long totalRecordedCallsCount = 0; - long totalCpuTime = 0; + private void dumpLocked(PrintWriter pw, AppIdToPackageMap packageMap, int workSourceUid, + boolean verbose) { + if (workSourceUid != Process.INVALID_UID) { + verbose = true; + } pw.print("Start time: "); pw.println(DateFormat.format("yyyy-MM-dd HH:mm:ss", mStartCurrentTime)); pw.print("On battery time (ms): "); pw.println(mBatteryStopwatch != null ? mBatteryStopwatch.getMillis() : 0); pw.println("Sampling interval period: " + mPeriodicSamplingInterval); - final List<UidEntry> entries = new ArrayList<>(); - final int uidEntriesSize = mUidEntries.size(); - for (int i = 0; i < uidEntriesSize; i++) { - UidEntry e = mUidEntries.valueAt(i); - entries.add(e); - totalCpuTime += e.cpuTimeMicros; - totalRecordedCallsCount += e.recordedCallCount; - totalCallsCount += e.callCount; - } - - entries.sort(Comparator.<UidEntry>comparingDouble(value -> value.cpuTimeMicros).reversed()); final String datasetSizeDesc = verbose ? "" : "(top 90% by cpu time) "; final StringBuilder sb = new StringBuilder(); pw.println("Per-UID raw data " + datasetSizeDesc @@ -467,10 +505,15 @@ public class BinderCallsStats implements BinderInternal.Observer { + "latency_time_micros, max_latency_time_micros, exception_count, " + "max_request_size_bytes, max_reply_size_bytes, recorded_call_count, " + "call_count):"); - final List<ExportedCallStat> exportedCallStats = getExportedCallStats(); + final List<ExportedCallStat> exportedCallStats; + if (workSourceUid != Process.INVALID_UID) { + exportedCallStats = getExportedCallStats(workSourceUid); + } else { + exportedCallStats = getExportedCallStats(); + } exportedCallStats.sort(BinderCallsStats::compareByCpuDesc); for (ExportedCallStat e : exportedCallStats) { - if (e.methodName.startsWith(DEBUG_ENTRY_PREFIX)) { + if (e.methodName != null && e.methodName.startsWith(DEBUG_ENTRY_PREFIX)) { // Do not dump debug entries. continue; } @@ -494,6 +537,30 @@ public class BinderCallsStats implements BinderInternal.Observer { pw.println(sb); } pw.println(); + final List<UidEntry> entries = new ArrayList<>(); + long totalCallsCount = 0; + long totalRecordedCallsCount = 0; + long totalCpuTime = 0; + + if (workSourceUid != Process.INVALID_UID) { + UidEntry e = getUidEntry(workSourceUid); + entries.add(e); + totalCpuTime += e.cpuTimeMicros; + totalRecordedCallsCount += e.recordedCallCount; + totalCallsCount += e.callCount; + } else { + final int uidEntriesSize = mUidEntries.size(); + for (int i = 0; i < uidEntriesSize; i++) { + UidEntry e = mUidEntries.valueAt(i); + entries.add(e); + totalCpuTime += e.cpuTimeMicros; + totalRecordedCallsCount += e.recordedCallCount; + totalCallsCount += e.callCount; + } + entries.sort( + Comparator.<UidEntry>comparingDouble(value -> value.cpuTimeMicros).reversed()); + } + pw.println("Per-UID Summary " + datasetSizeDesc + "(cpu_time, % of total cpu_time, recorded_call_count, call_count, package/uid):"); final List<UidEntry> summaryEntries = verbose ? entries @@ -505,10 +572,13 @@ public class BinderCallsStats implements BinderInternal.Observer { entry.recordedCallCount, entry.callCount, uidStr)); } pw.println(); - pw.println(String.format(" Summary: total_cpu_time=%d, " - + "calls_count=%d, avg_call_cpu_time=%.0f", - totalCpuTime, totalCallsCount, (double) totalCpuTime / totalRecordedCallsCount)); - pw.println(); + if (workSourceUid == Process.INVALID_UID) { + pw.println(String.format(" Summary: total_cpu_time=%d, " + + "calls_count=%d, avg_call_cpu_time=%.0f", + totalCpuTime, totalCallsCount, + (double) totalCpuTime / totalRecordedCallsCount)); + pw.println(); + } pw.println("Exceptions thrown (exception_count, class_name):"); final List<Pair<String, Integer>> exceptionEntries = new ArrayList<>(); @@ -590,6 +660,22 @@ public class BinderCallsStats implements BinderInternal.Observer { } } + /** + * Marks the specified work source UID for total binder call tracking: detailed information + * will be recorded for all calls from this source ID. + * + * This is expensive and can cause memory pressure, therefore this mode should only be used + * for debugging. + */ + public void recordAllCallsForWorkSourceUid(int workSourceUid) { + setDetailedTracking(true); + + Slog.i(TAG, "Recording all Binder calls for UID: " + workSourceUid); + UidEntry uidEntry = getUidEntry(workSourceUid); + uidEntry.recordAllTransactions = true; + mRecordingAllTransactionsForUid = true; + } + public void setAddDebugEntries(boolean addDebugEntries) { mAddDebugEntries = addDebugEntries; } @@ -637,6 +723,7 @@ public class BinderCallsStats implements BinderInternal.Observer { if (mBatteryStopwatch != null) { mBatteryStopwatch.reset(); } + mRecordingAllTransactionsForUid = false; } } @@ -767,6 +854,8 @@ public class BinderCallsStats implements BinderInternal.Observer { public long cpuTimeMicros; // Call count that gets reset after delivery to BatteryStats public long incrementalCallCount; + // Indicates that all transactions for the UID must be tracked + public boolean recordAllTransactions; UidEntry(int uid) { this.workSourceUid = uid; diff --git a/core/java/com/android/internal/os/BinderInternal.java b/core/java/com/android/internal/os/BinderInternal.java index f14d5f2bbbeb..2645b8e84cf1 100644 --- a/core/java/com/android/internal/os/BinderInternal.java +++ b/core/java/com/android/internal/os/BinderInternal.java @@ -85,9 +85,10 @@ public class BinderInternal { long timeStarted; // Should be set to one when an exception is thrown. boolean exceptionThrown; + // Detailed information should be recorded for this call when it ends. + public boolean recordedCall; } - /** * Responsible for resolving a work source. */ diff --git a/services/core/java/com/android/server/wm/ProtoLogGroup.java b/core/java/com/android/internal/protolog/ProtoLogGroup.java index 51725cecbc74..73d148c1f233 100644 --- a/services/core/java/com/android/server/wm/ProtoLogGroup.java +++ b/core/java/com/android/internal/protolog/ProtoLogGroup.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 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. @@ -14,11 +14,9 @@ * limitations under the License. */ -package com.android.server.wm; +package com.android.internal.protolog; -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.protolog.common.IProtoLogGroup; -import com.android.server.protolog.common.ProtoLog; +import com.android.internal.protolog.common.IProtoLogGroup; /** * Defines logging groups for ProtoLog. @@ -118,16 +116,6 @@ public enum ProtoLogGroup implements IProtoLogGroup { this.mLogToLogcat = logToLogcat; } - /** - * Test function for automated integration tests. Can be also called manually from adb shell. - */ - @VisibleForTesting - public static void testProtoLog() { - ProtoLog.e(ProtoLogGroup.TEST_GROUP, - "Test completed successfully: %b %d %o %x %e %g %f %% %s.", - true, 1, 2, 3, 0.4, 0.5, 0.6, "ok"); - } - private static class Consts { private static final String TAG_WM = "WindowManager"; diff --git a/services/core/java/com/android/server/protolog/ProtoLogImpl.java b/core/java/com/android/internal/protolog/ProtoLogImpl.java index c9d42c854b54..6874f10e6abc 100644 --- a/services/core/java/com/android/server/protolog/ProtoLogImpl.java +++ b/core/java/com/android/internal/protolog/ProtoLogImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 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. @@ -14,20 +14,20 @@ * limitations under the License. */ -package com.android.server.protolog; - -import static com.android.server.protolog.ProtoLogFileProto.LOG; -import static com.android.server.protolog.ProtoLogFileProto.MAGIC_NUMBER; -import static com.android.server.protolog.ProtoLogFileProto.MAGIC_NUMBER_H; -import static com.android.server.protolog.ProtoLogFileProto.MAGIC_NUMBER_L; -import static com.android.server.protolog.ProtoLogFileProto.REAL_TIME_TO_ELAPSED_TIME_OFFSET_MILLIS; -import static com.android.server.protolog.ProtoLogFileProto.VERSION; -import static com.android.server.protolog.ProtoLogMessage.BOOLEAN_PARAMS; -import static com.android.server.protolog.ProtoLogMessage.DOUBLE_PARAMS; -import static com.android.server.protolog.ProtoLogMessage.ELAPSED_REALTIME_NANOS; -import static com.android.server.protolog.ProtoLogMessage.MESSAGE_HASH; -import static com.android.server.protolog.ProtoLogMessage.SINT64_PARAMS; -import static com.android.server.protolog.ProtoLogMessage.STR_PARAMS; +package com.android.internal.protolog; + +import static com.android.internal.protolog.ProtoLogFileProto.LOG; +import static com.android.internal.protolog.ProtoLogFileProto.MAGIC_NUMBER; +import static com.android.internal.protolog.ProtoLogFileProto.MAGIC_NUMBER_H; +import static com.android.internal.protolog.ProtoLogFileProto.MAGIC_NUMBER_L; +import static com.android.internal.protolog.ProtoLogFileProto.REAL_TIME_TO_ELAPSED_TIME_OFFSET_MILLIS; +import static com.android.internal.protolog.ProtoLogFileProto.VERSION; +import static com.android.internal.protolog.ProtoLogMessage.BOOLEAN_PARAMS; +import static com.android.internal.protolog.ProtoLogMessage.DOUBLE_PARAMS; +import static com.android.internal.protolog.ProtoLogMessage.ELAPSED_REALTIME_NANOS; +import static com.android.internal.protolog.ProtoLogMessage.MESSAGE_HASH; +import static com.android.internal.protolog.ProtoLogMessage.SINT64_PARAMS; +import static com.android.internal.protolog.ProtoLogMessage.STR_PARAMS; import android.annotation.Nullable; import android.os.ShellCommand; @@ -36,10 +36,9 @@ import android.util.Slog; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; -import com.android.server.protolog.common.IProtoLogGroup; -import com.android.server.protolog.common.LogDataType; +import com.android.internal.protolog.common.IProtoLogGroup; +import com.android.internal.protolog.common.LogDataType; import com.android.internal.util.TraceBuffer; -import com.android.server.wm.ProtoLogGroup; import java.io.File; import java.io.IOException; @@ -62,7 +61,7 @@ public class ProtoLogImpl { * Must be invoked after every action that could change the result of {@link #isEnabled}, eg. * starting / stopping proto log, or enabling / disabling log groups. */ - static Runnable sCacheUpdater = () -> { }; + public static Runnable sCacheUpdater = () -> { }; private static void addLogGroupEnum(IProtoLogGroup[] config) { for (IProtoLogGroup group : config) { @@ -289,9 +288,7 @@ public class ProtoLogImpl { } } - - @VisibleForTesting - ProtoLogImpl(File file, int bufferCapacity, ProtoLogViewerConfigReader viewerConfig) { + public ProtoLogImpl(File file, int bufferCapacity, ProtoLogViewerConfigReader viewerConfig) { mLogFile = file; mBuffer = new TraceBuffer(bufferCapacity); mViewerConfig = viewerConfig; diff --git a/services/core/java/com/android/server/protolog/ProtoLogViewerConfigReader.java b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java index 494421717800..e381d30da524 100644 --- a/services/core/java/com/android/server/protolog/ProtoLogViewerConfigReader.java +++ b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 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. @@ -14,9 +14,7 @@ * limitations under the License. */ -package com.android.server.protolog; - -import static com.android.server.protolog.ProtoLogImpl.logAndPrintln; +package com.android.internal.protolog; import org.json.JSONException; import org.json.JSONObject; @@ -80,16 +78,17 @@ public class ProtoLogViewerConfigReader { // Not a messageHash - skip it } } - logAndPrintln(pw, "Loaded " + mLogMessageMap.size() + " log definitions from " - + viewerConfigFilename); + ProtoLogImpl.logAndPrintln(pw, "Loaded " + mLogMessageMap.size() + + " log definitions from " + viewerConfigFilename); } catch (FileNotFoundException e) { - logAndPrintln(pw, "Unable to load log definitions: File " + ProtoLogImpl.logAndPrintln(pw, "Unable to load log definitions: File " + viewerConfigFilename + " not found." + e); } catch (IOException e) { - logAndPrintln(pw, "Unable to load log definitions: IOException while reading " + ProtoLogImpl.logAndPrintln(pw, + "Unable to load log definitions: IOException while reading " + viewerConfigFilename + ". " + e); } catch (JSONException e) { - logAndPrintln(pw, + ProtoLogImpl.logAndPrintln(pw, "Unable to load log definitions: JSON parsing exception while reading " + viewerConfigFilename + ". " + e); } diff --git a/services/core/java/com/android/server/protolog/common/BitmaskConversionException.java b/core/java/com/android/internal/protolog/common/BitmaskConversionException.java index 7bb27b2d9bcd..68b9d6910b57 100644 --- a/services/core/java/com/android/server/protolog/common/BitmaskConversionException.java +++ b/core/java/com/android/internal/protolog/common/BitmaskConversionException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.protolog.common; +package com.android.internal.protolog.common; /** * Error while converting a bitmask representing a list of LogDataTypes. diff --git a/services/core/java/com/android/server/protolog/common/IProtoLogGroup.java b/core/java/com/android/internal/protolog/common/IProtoLogGroup.java index 2c65341453e9..e3db46832a6f 100644 --- a/services/core/java/com/android/server/protolog/common/IProtoLogGroup.java +++ b/core/java/com/android/internal/protolog/common/IProtoLogGroup.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.protolog.common; +package com.android.internal.protolog.common; /** * Defines a log group configuration object for ProtoLog. Should be implemented as en enum. diff --git a/services/core/java/com/android/server/protolog/common/InvalidFormatStringException.java b/core/java/com/android/internal/protolog/common/InvalidFormatStringException.java index 947bf98eea3c..97d3dfb7e6c2 100644 --- a/services/core/java/com/android/server/protolog/common/InvalidFormatStringException.java +++ b/core/java/com/android/internal/protolog/common/InvalidFormatStringException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.protolog.common; +package com.android.internal.protolog.common; /** * Unsupported/invalid message format string error. diff --git a/services/core/java/com/android/server/protolog/common/LogDataType.java b/core/java/com/android/internal/protolog/common/LogDataType.java index e73b41abddc7..651932a7ba7e 100644 --- a/services/core/java/com/android/server/protolog/common/LogDataType.java +++ b/core/java/com/android/internal/protolog/common/LogDataType.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.protolog.common; +package com.android.internal.protolog.common; import java.util.ArrayList; import java.util.List; diff --git a/services/core/java/com/android/server/protolog/common/ProtoLog.java b/core/java/com/android/internal/protolog/common/ProtoLog.java index b631bcb23f5f..ab58d351d3b9 100644 --- a/services/core/java/com/android/server/protolog/common/ProtoLog.java +++ b/core/java/com/android/internal/protolog/common/ProtoLog.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.protolog.common; +package com.android.internal.protolog.common; /** * ProtoLog API - exposes static logging methods. Usage of this API is similar diff --git a/core/java/com/android/internal/util/ScreenshotHelper.java b/core/java/com/android/internal/util/ScreenshotHelper.java index 9bf05135c4c5..a23fc4b57b45 100644 --- a/core/java/com/android/internal/util/ScreenshotHelper.java +++ b/core/java/com/android/internal/util/ScreenshotHelper.java @@ -291,7 +291,7 @@ public class ScreenshotHelper { }; Message msg = Message.obtain(null, screenshotType, screenshotRequest); - final ServiceConnection myConn = mScreenshotConnection; + Handler h = new Handler(handler.getLooper()) { @Override public void handleMessage(Message msg) { @@ -304,8 +304,8 @@ public class ScreenshotHelper { break; case SCREENSHOT_MSG_PROCESS_COMPLETE: synchronized (mScreenshotLock) { - if (myConn != null && mScreenshotConnection == myConn) { - mContext.unbindService(myConn); + if (mScreenshotConnection != null) { + mContext.unbindService(mScreenshotConnection); mScreenshotConnection = null; mScreenshotService = null; } @@ -368,6 +368,7 @@ public class ScreenshotHelper { } } else { Messenger messenger = new Messenger(mScreenshotService); + try { messenger.send(msg); } catch (RemoteException e) { diff --git a/core/java/com/android/internal/util/StatLogger.java b/core/java/com/android/internal/util/StatLogger.java index 29568d5020e3..2d65090ce51e 100644 --- a/core/java/com/android/internal/util/StatLogger.java +++ b/core/java/com/android/internal/util/StatLogger.java @@ -84,7 +84,7 @@ public class StatLogger { * give it back to the {@link #logDurationStat(int, long)}} after the event. */ public long getTime() { - return SystemClock.elapsedRealtimeNanos() / 1000; + return SystemClock.uptimeNanos() / 1000; } /** diff --git a/core/jni/android_os_SystemClock.cpp b/core/jni/android_os_SystemClock.cpp index b1f600053b9b..2fba445428f4 100644 --- a/core/jni/android_os_SystemClock.cpp +++ b/core/jni/android_os_SystemClock.cpp @@ -37,10 +37,12 @@ namespace android { static_assert(std::is_same<int64_t, jlong>::value, "jlong isn't an int64_t"); static_assert(std::is_same<decltype(uptimeMillis()), int64_t>::value, "uptimeMillis signature change, expected int64_t return value"); +static_assert(std::is_same<decltype(uptimeNanos()), int64_t>::value, + "uptimeNanos signature change, expected int64_t return value"); static_assert(std::is_same<decltype(elapsedRealtime()), int64_t>::value, - "uptimeMillis signature change, expected int64_t return value"); + "elapsedRealtime signature change, expected int64_t return value"); static_assert(std::is_same<decltype(elapsedRealtimeNano()), int64_t>::value, - "uptimeMillis signature change, expected int64_t return value"); + "elapsedRealtimeNano signature change, expected int64_t return value"); /* * native public static long currentThreadTimeMillis(); @@ -76,6 +78,7 @@ static const JNINativeMethod gMethods[] = { // All of these are @CriticalNative, so we can defer directly to SystemClock.h for // some of these { "uptimeMillis", "()J", (void*) uptimeMillis }, + { "uptimeNanos", "()J", (void*) uptimeNanos }, { "elapsedRealtime", "()J", (void*) elapsedRealtime }, { "elapsedRealtimeNanos", "()J", (void*) elapsedRealtimeNano }, diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index d6a773fb91e0..85b4fe197980 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -116,7 +116,6 @@ static struct { jfieldID width; jfieldID height; jfieldID useIdentityTransform; - jfieldID rotation; } gDisplayCaptureArgsClassInfo; static struct { @@ -325,8 +324,6 @@ static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env, captureArgs.useIdentityTransform = env->GetBooleanField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.useIdentityTransform); - captureArgs.rotation = ui::toRotation( - env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.rotation)); return captureArgs; } @@ -1849,8 +1846,6 @@ int register_android_view_SurfaceControl(JNIEnv* env) GetFieldIDOrDie(env, displayCaptureArgsClazz, "mHeight", "I"); gDisplayCaptureArgsClassInfo.useIdentityTransform = GetFieldIDOrDie(env, displayCaptureArgsClazz, "mUseIdentityTransform", "Z"); - gDisplayCaptureArgsClassInfo.rotation = - GetFieldIDOrDie(env, displayCaptureArgsClazz, "mRotation", "I"); jclass layerCaptureArgsClazz = FindClassOrDie(env, "android/view/SurfaceControl$LayerCaptureArgs"); diff --git a/core/proto/android/app/tvsettings_enums.proto b/core/proto/android/app/tvsettings_enums.proto index 31c5dd6b730a..4a3c59477f2f 100644 --- a/core/proto/android/app/tvsettings_enums.proto +++ b/core/proto/android/app/tvsettings_enums.proto @@ -168,7 +168,11 @@ enum ItemId { // Google Assistant > Personal results (toggle) ACCOUNT_SLICE_REG_ACCOUNT_ASSISTANT_PERSONAL_RESULTS = 0x12134000; - // Reserving [0x12140000, 0x12190000] for possible future settings + // TvSettings > Account & Sign In (Slice) > [A regular account] > + // Apps only mode (toggle) + ACCOUNT_SLICE_REG_ACCOUNT_APPS_ONLY_MODE = 0x12140000; + + // Reserving [0x12150000, 0x12190000] for possible future settings // TvSettings > Account & Sign In (Slice) > [A regular account] > Remove ACCOUNT_SLICE_REG_ACCOUNT_REMOVE = 0x121A0000; diff --git a/core/proto/android/server/protolog.proto b/core/proto/android/internal/protolog.proto index 34dc55b959c2..fee7a878f860 100644 --- a/core/proto/android/server/protolog.proto +++ b/core/proto/android/internal/protolog.proto @@ -16,7 +16,7 @@ syntax = "proto2"; -package com.android.server.protolog; +package com.android.internal.protolog; option java_multiple_files = true; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index fe290f3e97e8..edb972730f69 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1342,7 +1342,7 @@ android:priority="800" /> <!-- Allows an application to access data from sensors that the user uses to - measure what is happening inside his/her body, such as heart rate. + measure what is happening inside their body, such as heart rate. <p>Protection level: dangerous --> <permission android:name="android.permission.BODY_SENSORS" android:permissionGroup="android.permission-group.UNDEFINED" diff --git a/core/tests/coretests/src/android/app/WindowContextTest.java b/core/tests/coretests/src/android/app/WindowContextTest.java index 630e16ac80d4..0f9bc4bee99a 100644 --- a/core/tests/coretests/src/android/app/WindowContextTest.java +++ b/core/tests/coretests/src/android/app/WindowContextTest.java @@ -30,7 +30,6 @@ import android.view.Display; import android.view.IWindowManager; import android.view.WindowManagerGlobal; -import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; @@ -47,7 +46,6 @@ import org.junit.runner.RunWith; * <p>This test class is a part of Window Manager Service tests and specified in * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ -@FlakyTest(bugId = 150812449, detail = "Remove after confirmed it's stable.") @RunWith(AndroidJUnit4.class) @SmallTest @Presubmit diff --git a/core/tests/coretests/src/android/app/timezonedetector/TimeZoneCapabilitiesTest.java b/core/tests/coretests/src/android/app/timezonedetector/TimeZoneCapabilitiesTest.java index 8a36f1dc057b..72391f4d7dec 100644 --- a/core/tests/coretests/src/android/app/timezonedetector/TimeZoneCapabilitiesTest.java +++ b/core/tests/coretests/src/android/app/timezonedetector/TimeZoneCapabilitiesTest.java @@ -33,9 +33,11 @@ public class TimeZoneCapabilitiesTest { public void testEquals() { TimeZoneCapabilities.Builder builder1 = new TimeZoneCapabilities.Builder(ARBITRARY_USER_ID) .setConfigureAutoDetectionEnabled(CAPABILITY_POSSESSED) + .setConfigureGeoDetectionEnabled(CAPABILITY_POSSESSED) .setSuggestManualTimeZone(CAPABILITY_POSSESSED); TimeZoneCapabilities.Builder builder2 = new TimeZoneCapabilities.Builder(ARBITRARY_USER_ID) .setConfigureAutoDetectionEnabled(CAPABILITY_POSSESSED) + .setConfigureGeoDetectionEnabled(CAPABILITY_POSSESSED) .setSuggestManualTimeZone(CAPABILITY_POSSESSED); { TimeZoneCapabilities one = builder1.build(); @@ -57,6 +59,20 @@ public class TimeZoneCapabilitiesTest { assertEquals(one, two); } + builder2.setConfigureGeoDetectionEnabled(CAPABILITY_NOT_ALLOWED); + { + TimeZoneCapabilities one = builder1.build(); + TimeZoneCapabilities two = builder2.build(); + assertNotEquals(one, two); + } + + builder1.setConfigureGeoDetectionEnabled(CAPABILITY_NOT_ALLOWED); + { + TimeZoneCapabilities one = builder1.build(); + TimeZoneCapabilities two = builder2.build(); + assertEquals(one, two); + } + builder2.setSuggestManualTimeZone(CAPABILITY_NOT_ALLOWED); { TimeZoneCapabilities one = builder1.build(); @@ -76,12 +92,16 @@ public class TimeZoneCapabilitiesTest { public void testParcelable() { TimeZoneCapabilities.Builder builder = new TimeZoneCapabilities.Builder(ARBITRARY_USER_ID) .setConfigureAutoDetectionEnabled(CAPABILITY_POSSESSED) + .setConfigureGeoDetectionEnabled(CAPABILITY_POSSESSED) .setSuggestManualTimeZone(CAPABILITY_POSSESSED); assertRoundTripParcelable(builder.build()); builder.setConfigureAutoDetectionEnabled(CAPABILITY_NOT_ALLOWED); assertRoundTripParcelable(builder.build()); + builder.setConfigureGeoDetectionEnabled(CAPABILITY_NOT_ALLOWED); + assertRoundTripParcelable(builder.build()); + builder.setSuggestManualTimeZone(CAPABILITY_NOT_ALLOWED); assertRoundTripParcelable(builder.build()); } diff --git a/core/tests/coretests/src/android/app/timezonedetector/TimeZoneConfigurationTest.java b/core/tests/coretests/src/android/app/timezonedetector/TimeZoneConfigurationTest.java index ac7e9c437b63..00dc73ed269f 100644 --- a/core/tests/coretests/src/android/app/timezonedetector/TimeZoneConfigurationTest.java +++ b/core/tests/coretests/src/android/app/timezonedetector/TimeZoneConfigurationTest.java @@ -29,8 +29,9 @@ public class TimeZoneConfigurationTest { @Test public void testBuilder_copyConstructor() { - TimeZoneConfiguration.Builder builder1 = - new TimeZoneConfiguration.Builder().setAutoDetectionEnabled(true); + TimeZoneConfiguration.Builder builder1 = new TimeZoneConfiguration.Builder() + .setAutoDetectionEnabled(true) + .setGeoDetectionEnabled(true); TimeZoneConfiguration configuration1 = builder1.build(); TimeZoneConfiguration configuration2 = @@ -41,16 +42,15 @@ public class TimeZoneConfigurationTest { @Test public void testIsComplete() { - TimeZoneConfiguration incompleteConfiguration = - new TimeZoneConfiguration.Builder() - .build(); - assertFalse(incompleteConfiguration.isComplete()); + TimeZoneConfiguration.Builder builder = + new TimeZoneConfiguration.Builder(); + assertFalse(builder.build().isComplete()); - TimeZoneConfiguration completeConfiguration = - new TimeZoneConfiguration.Builder() - .setAutoDetectionEnabled(true) - .build(); - assertTrue(completeConfiguration.isComplete()); + builder.setAutoDetectionEnabled(true); + assertFalse(builder.build().isComplete()); + + builder.setGeoDetectionEnabled(true); + assertTrue(builder.build().isComplete()); } @Test @@ -122,6 +122,27 @@ public class TimeZoneConfigurationTest { TimeZoneConfiguration two = builder2.build(); assertEquals(one, two); } + + builder1.setGeoDetectionEnabled(true); + { + TimeZoneConfiguration one = builder1.build(); + TimeZoneConfiguration two = builder2.build(); + assertNotEquals(one, two); + } + + builder2.setGeoDetectionEnabled(false); + { + TimeZoneConfiguration one = builder1.build(); + TimeZoneConfiguration two = builder2.build(); + assertNotEquals(one, two); + } + + builder1.setGeoDetectionEnabled(false); + { + TimeZoneConfiguration one = builder1.build(); + TimeZoneConfiguration two = builder2.build(); + assertEquals(one, two); + } } @Test @@ -135,5 +156,11 @@ public class TimeZoneConfigurationTest { builder.setAutoDetectionEnabled(false); assertRoundTripParcelable(builder.build()); + + builder.setGeoDetectionEnabled(false); + assertRoundTripParcelable(builder.build()); + + builder.setGeoDetectionEnabled(true); + assertRoundTripParcelable(builder.build()); } } diff --git a/core/tests/coretests/src/android/view/WindowMetricsTest.java b/core/tests/coretests/src/android/view/WindowMetricsTest.java index ddc977d380ae..96df9dda23c7 100644 --- a/core/tests/coretests/src/android/view/WindowMetricsTest.java +++ b/core/tests/coretests/src/android/view/WindowMetricsTest.java @@ -27,7 +27,6 @@ import android.hardware.display.DisplayManager; import android.os.Handler; import android.platform.test.annotations.Presubmit; -import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; @@ -46,7 +45,6 @@ import org.junit.runner.RunWith; * <p>This test class is a part of Window Manager Service tests and specified in * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ -@FlakyTest(bugId = 148789183, detail = "Remove after confirmed it's stable.") @RunWith(AndroidJUnit4.class) @SmallTest @Presubmit diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java index 188ba9e0ca0e..96250db4aa51 100644 --- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import android.os.Binder; import android.os.Handler; @@ -44,6 +45,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Random; @@ -493,7 +495,9 @@ public class BinderCallsStatsTest { bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); PrintWriter pw = new PrintWriter(new StringWriter()); - bcs.dump(pw, new AppIdToPackageMap(new HashMap<>()), true); + bcs.dump(pw, new AppIdToPackageMap(new HashMap<>()), Process.INVALID_UID, true); + + bcs.dump(pw, new AppIdToPackageMap(new HashMap<>()), WORKSOURCE_UID, true); } @Test @@ -606,8 +610,8 @@ public class BinderCallsStatsTest { assertEquals("-1", callStats.methodName); assertEquals("com.android.internal.os.BinderCallsStats$OverflowBinder", callStats.className); - assertEquals(false , callStats.screenInteractive); - assertEquals(-1 , callStats.callingUid); + assertEquals(false, callStats.screenInteractive); + assertEquals(-1, callStats.callingUid); } @Test @@ -785,7 +789,7 @@ public class BinderCallsStatsTest { bcs.time += 30; bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); - for (Runnable runnable: mHandler.mRunnables) { + for (Runnable runnable : mHandler.mRunnables) { // Execute all pending runnables. Ignore the delay. runnable.run(); } @@ -839,6 +843,53 @@ public class BinderCallsStatsTest { assertEquals(3, tids[2]); } + @Test + public void testTrackingSpecificWorksourceUid() { + mDeviceState.setCharging(true); + + Binder binder = new Binder(); + + TestBinderCallsStats bcs = new TestBinderCallsStats(); + bcs.recordAllCallsForWorkSourceUid(WORKSOURCE_UID); + + int[] transactions = {41, 42, 43, 42, 43, 43}; + int[] durationsMs = {100, 200, 300, 400, 500, 600}; + + for (int i = 0; i < transactions.length; i++) { + CallSession callSession = bcs.callStarted(binder, transactions[i], WORKSOURCE_UID); + bcs.time += durationsMs[i]; + bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); + } + + BinderCallsStats.UidEntry uidEntry = bcs.getUidEntries().get(WORKSOURCE_UID); + Assert.assertNotNull(uidEntry); + assertEquals(6, uidEntry.callCount); + + Collection<BinderCallsStats.CallStat> callStatsList = uidEntry.getCallStatsList(); + assertEquals(3, callStatsList.size()); + for (BinderCallsStats.CallStat callStat : callStatsList) { + switch (callStat.transactionCode) { + case 41: + assertEquals(1, callStat.callCount); + assertEquals(1, callStat.incrementalCallCount); + assertEquals(100, callStat.cpuTimeMicros); + break; + case 42: + assertEquals(2, callStat.callCount); + assertEquals(2, callStat.incrementalCallCount); + assertEquals(200 + 400, callStat.cpuTimeMicros); + break; + case 43: + assertEquals(3, callStat.callCount); + assertEquals(3, callStat.incrementalCallCount); + assertEquals(300 + 500 + 600, callStat.cpuTimeMicros); + break; + default: + fail("Unexpected transaction code: " + callStat.transactionCode); + } + } + } + private static class TestHandler extends Handler { ArrayList<Runnable> mRunnables = new ArrayList<>(); diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java index 6e3fb1991acc..d4fb1be56890 100644 --- a/media/java/android/media/AudioDeviceInfo.java +++ b/media/java/android/media/AudioDeviceInfo.java @@ -147,6 +147,19 @@ public final class AudioDeviceInfo { // {@link android.media.audiopolicy.AudioMix#ROUTE_FLAG_LOOP_BACK} flag. public static final int TYPE_REMOTE_SUBMIX = 25; + /** + * A device type describing a Bluetooth Low Energy (BLE) audio headset or headphones. + * Headphones are grouped with headsets when the device is a sink: + * the features of headsets and headphones with regard to playback are the same. + */ + public static final int TYPE_BLE_HEADSET = 26; + + /** + * A device type describing a Bluetooth Low Energy (BLE) audio speaker. + */ + public static final int TYPE_BLE_SPEAKER = 27; + + /** @hide */ @IntDef(flag = false, prefix = "TYPE", value = { TYPE_BUILTIN_EARPIECE, @@ -171,7 +184,9 @@ public final class AudioDeviceInfo { TYPE_HEARING_AID, TYPE_BUILTIN_MIC, TYPE_FM_TUNER, - TYPE_TV_TUNER } + TYPE_TV_TUNER, + TYPE_BLE_HEADSET, + TYPE_BLE_SPEAKER} ) @Retention(RetentionPolicy.SOURCE) public @interface AudioDeviceType {} @@ -193,7 +208,8 @@ public final class AudioDeviceInfo { TYPE_LINE_ANALOG, TYPE_LINE_DIGITAL, TYPE_IP, - TYPE_BUS } + TYPE_BUS, + TYPE_BLE_HEADSET} ) @Retention(RetentionPolicy.SOURCE) public @interface AudioDeviceTypeIn {} @@ -219,7 +235,9 @@ public final class AudioDeviceInfo { TYPE_AUX_LINE, TYPE_IP, TYPE_BUS, - TYPE_HEARING_AID } + TYPE_HEARING_AID, + TYPE_BLE_HEADSET, + TYPE_BLE_SPEAKER} ) @Retention(RetentionPolicy.SOURCE) public @interface AudioDeviceTypeOut {} @@ -248,7 +266,8 @@ public final class AudioDeviceInfo { case TYPE_BUS: case TYPE_HEARING_AID: case TYPE_BUILTIN_SPEAKER_SAFE: - case TYPE_REMOTE_SUBMIX: + case TYPE_BLE_HEADSET: + case TYPE_BLE_SPEAKER: return true; default: return false; @@ -275,6 +294,7 @@ public final class AudioDeviceInfo { case TYPE_IP: case TYPE_BUS: case TYPE_REMOTE_SUBMIX: + case TYPE_BLE_HEADSET: return true; default: return false; @@ -527,6 +547,8 @@ public final class AudioDeviceInfo { INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPEAKER_SAFE, TYPE_BUILTIN_SPEAKER_SAFE); INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, TYPE_REMOTE_SUBMIX); + INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLE_HEADSET, TYPE_BLE_HEADSET); + INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLE_SPEAKER, TYPE_BLE_SPEAKER); INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUILTIN_MIC, TYPE_BUILTIN_MIC); INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET, TYPE_BLUETOOTH_SCO); @@ -547,6 +569,7 @@ public final class AudioDeviceInfo { INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_IP, TYPE_IP); INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUS, TYPE_BUS); INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_REMOTE_SUBMIX, TYPE_REMOTE_SUBMIX); + INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLE_HEADSET, TYPE_BLE_HEADSET); // privileges mapping to output device EXT_TO_INT_DEVICE_MAPPING = new SparseIntArray(); @@ -576,6 +599,8 @@ public final class AudioDeviceInfo { EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BUILTIN_SPEAKER_SAFE, AudioSystem.DEVICE_OUT_SPEAKER_SAFE); EXT_TO_INT_DEVICE_MAPPING.put(TYPE_REMOTE_SUBMIX, AudioSystem.DEVICE_OUT_REMOTE_SUBMIX); + EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_HEADSET, AudioSystem.DEVICE_OUT_BLE_HEADSET); + EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_SPEAKER, AudioSystem.DEVICE_OUT_BLE_SPEAKER); } } diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java index 42d0f0cc13c5..f6b04540c5c7 100644 --- a/media/java/android/media/AudioDevicePort.java +++ b/media/java/android/media/AudioDevicePort.java @@ -70,7 +70,9 @@ public class AudioDevicePort extends AudioPort { * {@link AudioManager#DEVICE_IN_USB_DEVICE}) use an address composed of the ALSA card number * and device number: "card=2;device=1" * - Bluetooth devices ({@link AudioManager#DEVICE_OUT_BLUETOOTH_SCO}, - * {@link AudioManager#DEVICE_OUT_BLUETOOTH_SCO}, {@link AudioManager#DEVICE_OUT_BLUETOOTH_A2DP}) + * {@link AudioManager#DEVICE_OUT_BLUETOOTH_SCO}, + * {@link AudioManager#DEVICE_OUT_BLUETOOTH_A2DP}), + * {@link AudioManager#DEVICE_OUT_BLE_HEADSET}, {@link AudioManager#DEVICE_OUT_BLE_SPEAKER}) * use the MAC address of the bluetooth device in the form "00:11:22:AA:BB:CC" as reported by * {@link BluetoothDevice#getAddress()}. * - Deivces that do not have an address will indicate an empty string "". diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 408f34be6b65..b2e0538fd4b8 100755 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -4413,6 +4413,18 @@ public class AudioManager { */ public static final int DEVICE_OUT_FM = AudioSystem.DEVICE_OUT_FM; /** @hide + * The audio output device code for echo reference injection point. + */ + public static final int DEVICE_OUT_ECHO_CANCELLER = AudioSystem.DEVICE_OUT_ECHO_CANCELLER; + /** @hide + * The audio output device code for a BLE audio headset. + */ + public static final int DEVICE_OUT_BLE_HEADSET = AudioSystem.DEVICE_OUT_BLE_HEADSET; + /** @hide + * The audio output device code for a BLE audio speaker. + */ + public static final int DEVICE_OUT_BLE_SPEAKER = AudioSystem.DEVICE_OUT_BLE_SPEAKER; + /** @hide * This is not used as a returned value from {@link #getDevicesForStream}, but could be * used in the future in a set method to select whatever default device is chosen by the * platform-specific implementation. @@ -4496,6 +4508,14 @@ public class AudioManager { * The audio input device code for audio loopback */ public static final int DEVICE_IN_LOOPBACK = AudioSystem.DEVICE_IN_LOOPBACK; + /** @hide + * The audio input device code for an echo reference capture point. + */ + public static final int DEVICE_IN_ECHO_REFERENCE = AudioSystem.DEVICE_IN_ECHO_REFERENCE; + /** @hide + * The audio input device code for a BLE audio headset. + */ + public static final int DEVICE_IN_BLE_HEADSET = AudioSystem.DEVICE_IN_BLE_HEADSET; /** * Return true if the device code corresponds to an output device. diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index da52cfef6bc6..5fe5c0580b0c 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -866,6 +866,12 @@ public class AudioSystem public static final int DEVICE_OUT_USB_HEADSET = 0x4000000; /** @hide */ public static final int DEVICE_OUT_HEARING_AID = 0x8000000; + /** @hide */ + public static final int DEVICE_OUT_ECHO_CANCELLER = 0x10000000; + /** @hide */ + public static final int DEVICE_OUT_BLE_HEADSET = 0x20000000; + /** @hide */ + public static final int DEVICE_OUT_BLE_SPEAKER = 0x20000001; /** @hide */ public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT; @@ -890,6 +896,8 @@ public class AudioSystem public static final Set<Integer> DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET; /** @hide */ public static final Set<Integer> DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET; + /** @hide */ + public static final Set<Integer> DEVICE_OUT_ALL_BLE_SET; static { DEVICE_OUT_ALL_SET = new HashSet<>(); DEVICE_OUT_ALL_SET.add(DEVICE_OUT_EARPIECE); @@ -920,6 +928,9 @@ public class AudioSystem DEVICE_OUT_ALL_SET.add(DEVICE_OUT_PROXY); DEVICE_OUT_ALL_SET.add(DEVICE_OUT_USB_HEADSET); DEVICE_OUT_ALL_SET.add(DEVICE_OUT_HEARING_AID); + DEVICE_OUT_ALL_SET.add(DEVICE_OUT_ECHO_CANCELLER); + DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLE_HEADSET); + DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLE_SPEAKER); DEVICE_OUT_ALL_SET.add(DEVICE_OUT_DEFAULT); DEVICE_OUT_ALL_A2DP_SET = new HashSet<>(); @@ -945,6 +956,10 @@ public class AudioSystem DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET = new HashSet<>(); DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET.addAll(DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET); DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET.add(DEVICE_OUT_SPEAKER); + + DEVICE_OUT_ALL_BLE_SET = new HashSet<>(); + DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_HEADSET); + DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_SPEAKER); } // input devices @@ -1019,6 +1034,8 @@ public class AudioSystem /** @hide */ public static final int DEVICE_IN_ECHO_REFERENCE = DEVICE_BIT_IN | 0x10000000; /** @hide */ + public static final int DEVICE_IN_BLE_HEADSET = DEVICE_BIT_IN | 0x20000000; + /** @hide */ @UnsupportedAppUsage public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT; @@ -1056,6 +1073,7 @@ public class AudioSystem DEVICE_IN_ALL_SET.add(DEVICE_IN_BLUETOOTH_BLE); DEVICE_IN_ALL_SET.add(DEVICE_IN_HDMI_ARC); DEVICE_IN_ALL_SET.add(DEVICE_IN_ECHO_REFERENCE); + DEVICE_IN_ALL_SET.add(DEVICE_IN_BLE_HEADSET); DEVICE_IN_ALL_SET.add(DEVICE_IN_DEFAULT); DEVICE_IN_ALL_SCO_SET = new HashSet<>(); @@ -1118,6 +1136,9 @@ public class AudioSystem /** @hide */ public static final String DEVICE_OUT_PROXY_NAME = "proxy"; /** @hide */ public static final String DEVICE_OUT_USB_HEADSET_NAME = "usb_headset"; /** @hide */ public static final String DEVICE_OUT_HEARING_AID_NAME = "hearing_aid_out"; + /** @hide */ public static final String DEVICE_OUT_ECHO_CANCELLER_NAME = "echo_canceller"; + /** @hide */ public static final String DEVICE_OUT_BLE_HEADSET_NAME = "ble_headset"; + /** @hide */ public static final String DEVICE_OUT_BLE_SPEAKER_NAME = "ble_speaker"; /** @hide */ public static final String DEVICE_IN_COMMUNICATION_NAME = "communication"; /** @hide */ public static final String DEVICE_IN_AMBIENT_NAME = "ambient"; @@ -1145,6 +1166,7 @@ public class AudioSystem /** @hide */ public static final String DEVICE_IN_BLUETOOTH_BLE_NAME = "bt_ble"; /** @hide */ public static final String DEVICE_IN_ECHO_REFERENCE_NAME = "echo_reference"; /** @hide */ public static final String DEVICE_IN_HDMI_ARC_NAME = "hdmi_arc"; + /** @hide */ public static final String DEVICE_IN_BLE_HEADSET_NAME = "ble_headset"; /** @hide */ @UnsupportedAppUsage @@ -1207,6 +1229,12 @@ public class AudioSystem return DEVICE_OUT_USB_HEADSET_NAME; case DEVICE_OUT_HEARING_AID: return DEVICE_OUT_HEARING_AID_NAME; + case DEVICE_OUT_ECHO_CANCELLER: + return DEVICE_OUT_ECHO_CANCELLER_NAME; + case DEVICE_OUT_BLE_HEADSET: + return DEVICE_OUT_BLE_HEADSET_NAME; + case DEVICE_OUT_BLE_SPEAKER: + return DEVICE_OUT_BLE_SPEAKER_NAME; case DEVICE_OUT_DEFAULT: default: return Integer.toString(device); @@ -1269,6 +1297,8 @@ public class AudioSystem return DEVICE_IN_ECHO_REFERENCE_NAME; case DEVICE_IN_HDMI_ARC: return DEVICE_IN_HDMI_ARC_NAME; + case DEVICE_IN_BLE_HEADSET: + return DEVICE_IN_BLE_HEADSET_NAME; case DEVICE_IN_DEFAULT: default: return Integer.toString(device); diff --git a/media/java/android/media/MediaTranscodeManager.java b/media/java/android/media/MediaTranscodeManager.java index e959e8e36b42..5d4404036102 100644 --- a/media/java/android/media/MediaTranscodeManager.java +++ b/media/java/android/media/MediaTranscodeManager.java @@ -225,13 +225,35 @@ public final class MediaTranscodeManager { job.updateStatusAndResult(TranscodingJob.STATUS_FINISHED, TranscodingJob.RESULT_ERROR); - // Notifies client the job is done. + // Notifies client the job failed. if (job.mListener != null && job.mListenerExecutor != null) { job.mListenerExecutor.execute(() -> job.mListener.onTranscodingFinished(job)); } } } + private void handleTranscodingProgressUpdate(int jobId, int newProgress) { + synchronized (mPendingTranscodingJobs) { + // Gets the job associated with the jobId. + final TranscodingJob job = mPendingTranscodingJobs.get(jobId); + + if (job == null) { + // This should not happen in reality. + Log.e(TAG, "Job " + jobId + " is not in PendingJobs"); + return; + } + + // Updates the job progress. + job.setJobProgress(newProgress); + + // Notifies client the progress update. + if (job.mProgressUpdateExecutor != null && job.mProgressUpdateListener != null) { + job.mProgressUpdateExecutor.execute( + () -> job.mProgressUpdateListener.onProgressUpdate(newProgress)); + } + } + } + // Just forwards all the events to the event handler. private ITranscodingClientCallback mTranscodingClientCallback = new ITranscodingClientCallback.Stub() { @@ -294,8 +316,8 @@ public final class MediaTranscodeManager { } @Override - public void onProgressUpdate(int jobId, int progress) throws RemoteException { - //TODO(hkuang): Implement this. + public void onProgressUpdate(int jobId, int newProgress) throws RemoteException { + handleTranscodingProgressUpdate(jobId, newProgress); } }; @@ -821,17 +843,8 @@ public final class MediaTranscodeManager { return mResult; } - private void setJobProgress(int newProgress) { - synchronized (this) { - mProgress = newProgress; - } - - // Notify listener. - OnProgressUpdateListener onProgressUpdateListener = mProgressUpdateListener; - if (mProgressUpdateListener != null) { - mProgressUpdateExecutor.execute( - () -> onProgressUpdateListener.onProgressUpdate(mProgress)); - } + private synchronized void setJobProgress(int newProgress) { + mProgress = newProgress; } } diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java index 3a5e69293a02..8e4153078174 100644 --- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java +++ b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java @@ -37,6 +37,7 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; /* * Functional tests for MediaTranscodeManager in the media framework. @@ -230,5 +231,63 @@ public class MediaTranscodeManagerTest 30, TimeUnit.MILLISECONDS); assertTrue("Fails to cancel transcoding", finishedOnTime); } + + + @Test + public void testTranscodingProgressUpdate() throws Exception { + Log.d(TAG, "Starting: testMediaTranscodeManager"); + + Semaphore transcodeCompleteSemaphore = new Semaphore(0); + + // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4 + // The full path of this file is: + // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4 + Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://" + + mContext.getCacheDir().getAbsolutePath() + "/HevcTranscode.mp4"); + + TranscodingRequest request = + new TranscodingRequest.Builder() + .setSourceUri(mSourceHEVCVideoUri) + .setDestinationUri(destinationUri) + .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO) + .setPriority(MediaTranscodeManager.PRIORITY_REALTIME) + .setVideoTrackFormat(createMediaFormat()) + .build(); + Executor listenerExecutor = Executors.newSingleThreadExecutor(); + + Log.i(TAG, "transcoding to " + createMediaFormat()); + + TranscodingJob job = mMediaTranscodeManager.enqueueRequest(request, listenerExecutor, + transcodingJob -> { + Log.d(TAG, "Transcoding completed with result: " + transcodingJob.getResult()); + assertEquals(transcodingJob.getResult(), TranscodingJob.RESULT_SUCCESS); + transcodeCompleteSemaphore.release(); + }); + assertNotNull(job); + + AtomicInteger progressUpdateCount = new AtomicInteger(0); + + // Set progress update executor and use the same executor as result listener. + job.setOnProgressUpdateListener(listenerExecutor, + new TranscodingJob.OnProgressUpdateListener() { + int mPreviousProgress = 0; + + @Override + public void onProgressUpdate(int newProgress) { + assertTrue("Invalid proress update", newProgress > mPreviousProgress); + assertTrue("Invalid proress update", newProgress <= 100); + mPreviousProgress = newProgress; + progressUpdateCount.getAndIncrement(); + Log.i(TAG, "Get progress update " + newProgress); + } + }); + + Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to cancel."); + boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire( + TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS); + assertTrue("Transcode failed to complete in time.", finishedOnTime); + assertTrue("Failed to receive at least 10 progress updates", + progressUpdateCount.get() > 10); + } } diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt index 70ef69d8ce72..51e7287bfd72 100644 --- a/non-updatable-api/current.txt +++ b/non-updatable-api/current.txt @@ -5596,6 +5596,7 @@ package android.app { method public android.graphics.drawable.Icon getIcon(); method public android.app.RemoteInput[] getRemoteInputs(); method public int getSemanticAction(); + method public boolean isAuthenticationRequired(); method public boolean isContextual(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.Notification.Action> CREATOR; @@ -5625,6 +5626,7 @@ package android.app { method @NonNull public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Extender); method @NonNull public android.os.Bundle getExtras(); method @NonNull public android.app.Notification.Action.Builder setAllowGeneratedReplies(boolean); + method @NonNull public android.app.Notification.Action.Builder setAuthenticationRequired(boolean); method @NonNull public android.app.Notification.Action.Builder setContextual(boolean); method @NonNull public android.app.Notification.Action.Builder setSemanticAction(int); } @@ -24047,6 +24049,8 @@ package android.media { method public boolean isSink(); method public boolean isSource(); field public static final int TYPE_AUX_LINE = 19; // 0x13 + field public static final int TYPE_BLE_HEADSET = 26; // 0x1a + field public static final int TYPE_BLE_SPEAKER = 27; // 0x1b field public static final int TYPE_BLUETOOTH_A2DP = 8; // 0x8 field public static final int TYPE_BLUETOOTH_SCO = 7; // 0x7 field public static final int TYPE_BUILTIN_EARPIECE = 1; // 0x1 diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt index 86ac3e477dc4..35b483b9fb84 100644 --- a/non-updatable-api/module-lib-current.txt +++ b/non-updatable-api/module-lib-current.txt @@ -54,6 +54,7 @@ package android.os { } public interface Parcelable { + method public default int getStability(); field public static final int PARCELABLE_STABILITY_LOCAL = 0; // 0x0 field public static final int PARCELABLE_STABILITY_VINTF = 1; // 0x1 } diff --git a/packages/CarSystemUI/samples/sample1/rro/Android.bp b/packages/CarSystemUI/samples/sample1/rro/Android.bp new file mode 100644 index 000000000000..5b0347ff73fd --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/Android.bp @@ -0,0 +1,27 @@ +// +// Copyright (C) 2020 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. +// + +android_app { + name: "CarSystemUISampleOneRRO", + resource_dirs: ["res"], + certificate: "platform", + platform_apis: true, + manifest: "AndroidManifest.xml", + aaptflags: [ + "--no-resource-deduping", + "--no-resource-removal", + ] +}
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/AndroidManifest.xml b/packages/CarSystemUI/samples/sample1/rro/AndroidManifest.xml new file mode 100644 index 000000000000..5c25056f7915 --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/AndroidManifest.xml @@ -0,0 +1,24 @@ +<!-- + ~ Copyright (C) 2020 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. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.systemui.rro"> + <overlay + android:targetPackage="com.android.systemui" + android:isStatic="false" + android:resourcesMap="@xml/car_sysui_overlays" + /> +</manifest>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/values/config.xml b/packages/CarSystemUI/samples/sample1/rro/res/values/config.xml new file mode 100644 index 000000000000..854ab7d7e49b --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/values/config.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 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. + --> + +<resources> + <!-- Configure which system bars should be displayed. --> + <bool name="config_enableTopNavigationBar">true</bool> + <bool name="config_enableLeftNavigationBar">true</bool> + <bool name="config_enableRightNavigationBar">true</bool> + <bool name="config_enableBottomNavigationBar">true</bool> + + <!-- Configure the type of each system bar. Each system bar must have a unique type. --> + <!-- STATUS_BAR = 0--> + <!-- NAVIGATION_BAR = 1--> + <!-- STATUS_BAR_EXTRA = 2--> + <!-- NAVIGATION_BAR_EXTRA = 3--> + <integer name="config_topSystemBarType">0</integer> + <integer name="config_leftSystemBarType">2</integer> + <integer name="config_rightSystemBarType">3</integer> + <integer name="config_bottomSystemBarType">1</integer> + + <!-- Configure the relative z-order among the system bars. When two system bars overlap (e.g. + if both top bar and left bar are enabled, it creates an overlapping space in the upper left + corner), the system bar with the higher z-order takes the overlapping space and padding is + applied to the other bar.--> + <!-- NOTE: If two overlapping system bars have the same z-order, SystemBarConfigs will throw a + RuntimeException, since their placing order cannot be determined. Bars that do not overlap + are allowed to have the same z-order. --> + <!-- NOTE: If the z-order of a bar is 10 or above, it will also appear on top of HUN's. --> + <integer name="config_topSystemBarZOrder">1</integer> + <integer name="config_leftSystemBarZOrder">0</integer> + <integer name="config_rightSystemBarZOrder">0</integer> + <integer name="config_bottomSystemBarZOrder">10</integer> +</resources>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/xml/car_sysui_overlays.xml b/packages/CarSystemUI/samples/sample1/rro/res/xml/car_sysui_overlays.xml new file mode 100644 index 000000000000..7bcb8e1b43dd --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/xml/car_sysui_overlays.xml @@ -0,0 +1,33 @@ + +<!-- + ~ Copyright (C) 2020 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. + --> + +<overlay> + <item target="bool/config_enableTopNavigationBar" value="@bool/config_enableTopNavigationBar"/> + <item target="bool/config_enableLeftNavigationBar" value="@bool/config_enableLeftNavigationBar"/> + <item target="bool/config_enableRightNavigationBar" value="@bool/config_enableRightNavigationBar"/> + <item target="bool/config_enableBottomNavigationBar" value="@bool/config_enableBottomNavigationBar"/> + + <item target="integer/config_topSystemBarType" value="@integer/config_topSystemBarType"/> + <item target="integer/config_leftSystemBarType" value="@integer/config_leftSystemBarType"/> + <item target="integer/config_rightSystemBarType" value="@integer/config_rightSystemBarType"/> + <item target="integer/config_bottomSystemBarType" value="@integer/config_bottomSystemBarType"/> + + <item target="integer/config_topSystemBarZOrder" value="@integer/config_topSystemBarZOrder"/> + <item target="integer/config_leftSystemBarZOrder" value="@integer/config_leftSystemBarZOrder"/> + <item target="integer/config_rightSystemBarZOrder" value="@integer/config_rightSystemBarZOrder"/> + <item target="integer/config_bottomSystemBarZOrder" value="@integer/config_bottomSystemBarZOrder"/> +</overlay>
\ No newline at end of file diff --git a/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java b/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java index 8efbad64f3d2..2c4545e7b265 100644 --- a/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java +++ b/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java @@ -155,41 +155,6 @@ public class FusedLocationServiceTest { assertThat(mManager.getNextLocation(TIMEOUT_MS)).isEqualTo(location); } - @Test - public void testBypassRequest() throws Exception { - LocationRequest request = LocationRequest.createFromDeprecatedProvider(FUSED_PROVIDER, 1000, - 0, false).setQuality(LocationRequest.POWER_HIGH).setLocationSettingsIgnored(true); - - mProvider.setRequest( - new ProviderRequest.Builder() - .setInterval(1000) - .setLocationSettingsIgnored(true) - .setLocationRequests(Collections.singletonList(request)) - .build(), - new WorkSource()); - - boolean containsNetworkBypass = false; - for (LocationRequest iRequest : mLocationManager.getTestProviderCurrentRequests( - NETWORK_PROVIDER)) { - if (iRequest.isLocationSettingsIgnored()) { - containsNetworkBypass = true; - break; - } - } - - boolean containsGpsBypass = false; - for (LocationRequest iRequest : mLocationManager.getTestProviderCurrentRequests( - GPS_PROVIDER)) { - if (iRequest.isLocationSettingsIgnored()) { - containsGpsBypass = true; - break; - } - } - - assertThat(containsNetworkBypass).isTrue(); - assertThat(containsGpsBypass).isTrue(); - } - private static class LocationProviderManagerCapture extends ILocationProviderManager.Stub { private final LinkedBlockingQueue<Location> mLocations; diff --git a/packages/Shell/src/com/android/shell/Screenshooter.java b/packages/Shell/src/com/android/shell/Screenshooter.java index 8e0161961a49..85f25528f07e 100644 --- a/packages/Shell/src/com/android/shell/Screenshooter.java +++ b/packages/Shell/src/com/android/shell/Screenshooter.java @@ -17,11 +17,8 @@ package com.android.shell; import android.graphics.Bitmap; -import android.graphics.Point; -import android.graphics.Rect; -import android.hardware.display.DisplayManagerGlobal; +import android.os.IBinder; import android.util.Log; -import android.view.Display; import android.view.SurfaceControl; /** @@ -40,22 +37,17 @@ final class Screenshooter { * @return The screenshot bitmap on success, null otherwise. */ static Bitmap takeScreenshot() { - Display display = DisplayManagerGlobal.getInstance() - .getRealDisplay(Display.DEFAULT_DISPLAY); - Point displaySize = new Point(); - display.getRealSize(displaySize); - final int displayWidth = displaySize.x; - final int displayHeight = displaySize.y; - - int rotation = display.getRotation(); - Rect crop = new Rect(0, 0, displayWidth, displayHeight); - Log.d(TAG, "Taking screenshot of dimensions " + displayWidth + " x " + displayHeight); + Log.d(TAG, "Taking fullscreen screenshot"); // Take the screenshot - Bitmap screenShot = - SurfaceControl.screenshot(crop, displayWidth, displayHeight, rotation); + final IBinder displayToken = SurfaceControl.getInternalDisplayToken(); + final SurfaceControl.DisplayCaptureArgs captureArgs = + new SurfaceControl.DisplayCaptureArgs.Builder(displayToken) + .build(); + final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer = + SurfaceControl.captureDisplay(captureArgs); + final Bitmap screenShot = screenshotBuffer == null ? null : screenshotBuffer.asBitmap(); if (screenShot == null) { - Log.e(TAG, "Failed to take screenshot of dimensions " + displayWidth + " x " - + displayHeight); + Log.e(TAG, "Failed to take fullscreen screenshot"); return null; } diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml index 53eb2343d26a..401f3e3e0685 100644 --- a/packages/SystemUI/res-keyguard/values/styles.xml +++ b/packages/SystemUI/res-keyguard/values/styles.xml @@ -27,6 +27,7 @@ <item name="android:textColor">?attr/wallpaperTextColorSecondary</item> <item name="android:textSize">14dp</item> <item name="android:background">@drawable/kg_emergency_button_background</item> + <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item> <item name="android:paddingLeft">12dp</item> <item name="android:paddingRight">12dp</item> </style> diff --git a/packages/SystemUI/res/drawable-television/ic_volume_media.xml b/packages/SystemUI/res/drawable-television/ic_volume_media.xml new file mode 100644 index 000000000000..e43c4b471db4 --- /dev/null +++ b/packages/SystemUI/res/drawable-television/ic_volume_media.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2020 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 + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="@color/tv_volume_dialog_accent" + android:pathData="M3,9v6h4l5,5L12,4L7,9L3,9zM16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02zM14,3.23v2.06c2.89,0.86 5,3.54 5,6.71s-2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77s-2.99,-7.86 -7,-8.77z"/> +</vector> diff --git a/packages/SystemUI/res/drawable-television/ic_volume_media_low.xml b/packages/SystemUI/res/drawable-television/ic_volume_media_low.xml new file mode 100644 index 000000000000..0f6dc9517f53 --- /dev/null +++ b/packages/SystemUI/res/drawable-television/ic_volume_media_low.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2020 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 + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="@color/tv_volume_dialog_accent" + android:pathData="M3,15V9H7L12,4V20L7,15H3ZM14,7.97C15.48,8.71 16.5,10.23 16.5,12C16.5,13.77 15.48,15.29 14,16.02V7.97Z"/> +</vector> diff --git a/packages/SystemUI/res/drawable-television/ic_volume_media_mute.xml b/packages/SystemUI/res/drawable-television/ic_volume_media_mute.xml new file mode 100644 index 000000000000..4b59e13516d2 --- /dev/null +++ b/packages/SystemUI/res/drawable-television/ic_volume_media_mute.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2020 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 + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="@color/tv_volume_dialog_accent" + android:pathData="M16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v2.21l2.45,2.45c0.03,-0.2 0.05,-0.41 0.05,-0.63zM19,12c0,0.94 -0.2,1.82 -0.54,2.64l1.51,1.51C20.63,14.91 21,13.5 21,12c0,-4.28 -2.99,-7.86 -7,-8.77v2.06c2.89,0.86 5,3.54 5,6.71zM4.27,3L3,4.27 7.73,9L3,9v6h4l5,5v-6.73l4.25,4.25c-0.67,0.52 -1.42,0.93 -2.25,1.18v2.06c1.38,-0.31 2.63,-0.95 3.69,-1.81L19.73,21 21,19.73l-9,-9L4.27,3zM12,4L9.91,6.09 12,8.18L12,4z"/> +</vector> + diff --git a/packages/SystemUI/res/drawable/ic_volume_media_low.xml b/packages/SystemUI/res/drawable/ic_volume_media_low.xml new file mode 100644 index 000000000000..87591de39d54 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_volume_media_low.xml @@ -0,0 +1,18 @@ +<!-- + Copyright (C) 2020 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. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:drawable="@drawable/ic_volume_media" /> +</selector> diff --git a/packages/SystemUI/res/drawable/tv_volume_dialog_background.xml b/packages/SystemUI/res/drawable/tv_volume_dialog_background.xml new file mode 100644 index 000000000000..fee6e57d2e86 --- /dev/null +++ b/packages/SystemUI/res/drawable/tv_volume_dialog_background.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 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. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + + <solid android:color="@color/tv_volume_dialog_background" /> + <corners android:radius="@dimen/tv_volume_dialog_corner_radius"/> + +</shape> diff --git a/packages/SystemUI/res/drawable/tv_volume_dialog_circle.xml b/packages/SystemUI/res/drawable/tv_volume_dialog_circle.xml new file mode 100644 index 000000000000..3c4fc05914f8 --- /dev/null +++ b/packages/SystemUI/res/drawable/tv_volume_dialog_circle.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 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. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="oval"> + <solid android:color="@color/tv_volume_dialog_circle" /> + +</shape> diff --git a/packages/SystemUI/res/layout-land-television/volume_dialog.xml b/packages/SystemUI/res/layout-land-television/volume_dialog.xml index e0d158d757b3..56d847c6aa2e 100644 --- a/packages/SystemUI/res/layout-land-television/volume_dialog.xml +++ b/packages/SystemUI/res/layout-land-television/volume_dialog.xml @@ -20,7 +20,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/transparent" - android:theme="@style/qs_theme"> + android:theme="@style/volume_dialog_theme"> <FrameLayout android:id="@+id/volume_dialog" @@ -46,7 +46,7 @@ android:translationZ="@dimen/volume_dialog_elevation" android:clipChildren="false" android:clipToPadding="false" - android:background="@drawable/rounded_bg_full"> + android:background="@drawable/tv_volume_dialog_background"> <LinearLayout android:id="@+id/volume_dialog_rows" @@ -54,9 +54,7 @@ android:layout_height="wrap_content" android:minWidth="@dimen/volume_dialog_panel_width" android:gravity="center" - android:orientation="horizontal" - android:paddingRight="@dimen/volume_dialog_stream_padding" - android:paddingLeft="@dimen/volume_dialog_stream_padding"> + android:orientation="horizontal"> <!-- volume rows added and removed here! :-) --> </LinearLayout> @@ -98,4 +96,4 @@ </FrameLayout> -</FrameLayout>
\ No newline at end of file +</FrameLayout> diff --git a/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml b/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml index 08209ab09169..c0f0aa8bbc8d 100644 --- a/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml +++ b/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml @@ -21,11 +21,12 @@ android:background="@android:color/transparent" android:clipChildren="false" android:clipToPadding="false" - android:theme="@style/qs_theme"> + android:theme="@style/volume_dialog_theme"> <LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" + android:padding="@dimen/tv_volume_dialog_row_padding" android:background="@android:color/transparent" android:gravity="center" android:layout_gravity="center" @@ -33,9 +34,9 @@ <com.android.keyguard.AlphaOptimizedImageButton android:id="@+id/volume_row_icon" style="@style/VolumeButtons" - android:layout_width="@dimen/volume_dialog_tap_target_size" - android:layout_height="@dimen/volume_dialog_tap_target_size" - android:background="@drawable/ripple_drawable_20dp" + android:layout_width="@dimen/tv_volume_dialog_bubble_size" + android:layout_height="@dimen/tv_volume_dialog_bubble_size" + android:background="@drawable/tv_volume_dialog_circle" android:tint="@color/accent_tint_color_selector" android:soundEffectsEnabled="false" /> <TextView @@ -62,6 +63,15 @@ android:layout_gravity="center" android:rotation="0" /> </FrameLayout> + <TextView + android:id="@+id/volume_number" + android:layout_width="@dimen/tv_volume_dialog_bubble_size" + android:layout_height="@dimen/tv_volume_dialog_bubble_size" + android:maxLength="2" + android:gravity="center" + android:background="@drawable/tv_volume_dialog_circle" + android:textSize="@dimen/tv_volume_number_text_size" + android:textColor="@color/accent_tint_color_selector"/> </LinearLayout> <include layout="@layout/volume_dnd_icon"/> diff --git a/packages/SystemUI/res/layout-land/volume_dialog.xml b/packages/SystemUI/res/layout-land/volume_dialog.xml index 5da7819c3d76..c420117073c5 100644 --- a/packages/SystemUI/res/layout-land/volume_dialog.xml +++ b/packages/SystemUI/res/layout-land/volume_dialog.xml @@ -22,7 +22,7 @@ android:gravity="right" android:layout_gravity="right" android:background="@android:color/transparent" - android:theme="@style/qs_theme"> + android:theme="@style/volume_dialog_theme"> <FrameLayout android:id="@+id/volume_dialog" diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml index 7d6547b9cd42..a90b1eb471ff 100644 --- a/packages/SystemUI/res/layout/volume_dialog.xml +++ b/packages/SystemUI/res/layout/volume_dialog.xml @@ -22,7 +22,7 @@ android:gravity="right" android:layout_gravity="right" android:background="@android:color/transparent" - android:theme="@style/qs_theme"> + android:theme="@style/volume_dialog_theme"> <!-- right-aligned to be physically near volume button --> <LinearLayout diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml index 6128da8627a9..b9efc5be70c1 100644 --- a/packages/SystemUI/res/layout/volume_dialog_row.xml +++ b/packages/SystemUI/res/layout/volume_dialog_row.xml @@ -20,7 +20,7 @@ android:layout_width="@dimen/volume_dialog_panel_width" android:clipChildren="false" android:clipToPadding="false" - android:theme="@style/qs_theme"> + android:theme="@style/volume_dialog_theme"> <LinearLayout android:layout_height="wrap_content" diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index ee8700261db5..bac915d854d8 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -1069,7 +1069,7 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Laai tans aanbevelings"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Versteek die huidige sessie."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Versteek"</string> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Maak toe"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Hervat"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Instellings"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Onaktief, gaan program na"</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 03eb39659ef3..aedbded46298 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ምክሮችን በመጫን ላይ"</string> <string name="controls_media_title" msgid="1746947284862928133">"ሚዲያ"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"የአሁኑን ክፍለ-ጊዜ ደብቅ።"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ደብቅ"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"ከቆመበት ቀጥል"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"ቅንብሮች"</string> <string name="controls_error_timeout" msgid="794197289772728958">"ንቁ ያልኾነ፣ መተግበሪያን ይፈትሹ"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 95d54a2386dd..fee86ca42fe6 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -1093,7 +1093,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"جارٍ تحميل الاقتراحات"</string> <string name="controls_media_title" msgid="1746947284862928133">"الوسائط"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"إخفاء الجلسة الحالية"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"إخفاء"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"استئناف التشغيل"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"الإعدادات"</string> <string name="controls_error_timeout" msgid="794197289772728958">"غير نشط، تحقّق من التطبيق."</string> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index 3023a27b15b4..3778df80197b 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"চুপাৰিছসমূহ ল’ড কৰি থকা হৈছে"</string> <string name="controls_media_title" msgid="1746947284862928133">"মিডিয়া"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"বৰ্তমানৰ ছেশ্বনটো লুকুৱাওক।"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"লুকুৱাওক"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"পুনৰ আৰম্ভ কৰক"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"ছেটিংসমূহ"</string> <string name="controls_error_timeout" msgid="794197289772728958">"সক্ৰিয় নহয়, এপ্টো পৰীক্ষা কৰক"</string> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 3c8e04b7ba35..874bf7465827 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Tövsiyələr yüklənir"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Cari sessiyanı gizlədin."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Gizlədin"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Davam edin"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Ayarlar"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Aktiv deyil, tətbiqi yoxlayın"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 4b400eb479c9..2a120c57e955 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -1075,7 +1075,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavaju se preporuke"</string> <string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Sakrijte aktuelnu sesiju."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sakrij"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Podešavanja"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno. Vidite aplikaciju"</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index f1064fb7b1d7..e4bb67ae65c6 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -1081,7 +1081,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Загружаюцца рэкамендацыі"</string> <string name="controls_media_title" msgid="1746947284862928133">"Мультымедыя"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Схаваць цяперашні сеанс."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Схаваць"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Узнавіць"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Налады"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Неактыўна, праверце праграму"</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 8ba2a1e51769..c51e58ccd6cf 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Препоръките се зареждат"</string> <string name="controls_media_title" msgid="1746947284862928133">"Мултимедия"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Скриване на текущата сесия."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Скриване"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Възобновяване"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Настройки"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, проверете прилож."</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 5861c44c1cbb..3d00ca858ef5 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"সাজেশন লোড করা হচ্ছে"</string> <string name="controls_media_title" msgid="1746947284862928133">"মিডিয়া"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"বর্তমান সেশন লুকান।"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"লুকান"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"আবার চালু করুন"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"সেটিংস"</string> <string name="controls_error_timeout" msgid="794197289772728958">"বন্ধ আছে, অ্যাপ চেক করুন"</string> @@ -1084,8 +1085,6 @@ <string name="controls_added_tooltip" msgid="4842812921719153085">"নতুন কন্ট্রোল দেখতে পাওয়ার বোতাম টিপে ধরে থাকুন"</string> <string name="controls_menu_add" msgid="4447246119229920050">"কন্ট্রোল যোগ করুন"</string> <string name="controls_menu_edit" msgid="890623986951347062">"কন্ট্রোল এডিট করুন"</string> - <!-- no translation found for one_handed_tutorial_title (6312198435090726656) --> - <skip /> - <!-- no translation found for one_handed_tutorial_description (7674850272340517174) --> - <skip /> + <string name="one_handed_tutorial_title" msgid="6312198435090726656">"\'এক হাতে ব্যবহার করার মোড\'-এর ব্যবহার"</string> + <string name="one_handed_tutorial_description" msgid="7674850272340517174">"বেরিয়ে আসার জন্য, স্ক্রিনের নিচ থেকে উপরের দিকে সোয়াইপ করুন অথবা অ্যাপের আইকনের উপরে যেকোনও জায়গায় ট্যাপ করুন"</string> </resources> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 984cbebd42eb..14259840d503 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -1075,7 +1075,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavanje preporuka"</string> <string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Sakrijte trenutnu sesiju."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sakrij"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Postavke"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, vidite aplikaciju"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index b8c41efa7813..b1501558f924 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregant les recomanacions"</string> <string name="controls_media_title" msgid="1746947284862928133">"Multimèdia"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Amaga la sessió actual."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Amaga"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Reprèn"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Configuració"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactiu; comprova l\'aplicació"</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index f946cc4f9552..ae6cc13cd1df 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -1081,7 +1081,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Načítání doporučení"</string> <string name="controls_media_title" msgid="1746947284862928133">"Média"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Skrýt aktuální relaci."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skrýt"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Pokračovat"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavení"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Neaktivní, zkontrolujte aplikaci"</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index a6de8a618f23..09f7f1a8762e 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Indlæser anbefalinger"</string> <string name="controls_media_title" msgid="1746947284862928133">"Medie"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Skjul den aktuelle session."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skjul"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Genoptag"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Indstillinger"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Tjek appen"</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 372cc1166fce..2410e4785c8d 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Empfehlungen werden geladen"</string> <string name="controls_media_title" msgid="1746947284862928133">"Medien"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Du kannst die aktuelle Sitzung ausblenden."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ausblenden"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Fortsetzen"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Einstellungen"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv – sieh in der App nach"</string> @@ -1084,8 +1085,6 @@ <string name="controls_added_tooltip" msgid="4842812921719153085">"Zum Anzeigen der Karten für neue Geräte Ein-/Aus-Taste gedrückt halten"</string> <string name="controls_menu_add" msgid="4447246119229920050">"Steuerelemente hinzufügen"</string> <string name="controls_menu_edit" msgid="890623986951347062">"Steuerelemente bearbeiten"</string> - <!-- no translation found for one_handed_tutorial_title (6312198435090726656) --> - <skip /> - <!-- no translation found for one_handed_tutorial_description (7674850272340517174) --> - <skip /> + <string name="one_handed_tutorial_title" msgid="6312198435090726656">"Einhandmodus verwenden"</string> + <string name="one_handed_tutorial_description" msgid="7674850272340517174">"Wenn du die App schließen möchtest, wische vom unteren Rand des Displays nach oben oder tippe auf eine beliebige Stelle oberhalb der App"</string> </resources> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index b4673476bad5..f66c5a88b102 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Φόρτωση προτάσεων"</string> <string name="controls_media_title" msgid="1746947284862928133">"Μέσα"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Απόκρυψη της τρέχουσας περιόδου λειτουργίας."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Απόκρυψη"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Συνέχιση"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Ρυθμίσεις"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Ανενεργό, έλεγχος εφαρμογής"</string> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 7fa7f83c5f12..0e22b583352c 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -1069,7 +1069,7 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index f73dad3a8bef..acf087d51181 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -1069,7 +1069,7 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 7fa7f83c5f12..0e22b583352c 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -1069,7 +1069,7 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 7fa7f83c5f12..0e22b583352c 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -1069,7 +1069,7 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 6140bf1eea3d..4f4238a5eb45 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -1069,7 +1069,7 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 6818116ec9b5..45e072496b25 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendaciones"</string> <string name="controls_media_title" msgid="1746947284862928133">"Contenido multimedia"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Oculta la sesión actual."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Reanudar"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Configuración"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Verifica la app"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index f09a0d24b26e..f7ebbd02708a 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendaciones"</string> <string name="controls_media_title" msgid="1746947284862928133">"Multimedia"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Ocultar la sesión."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Reanudar"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Ajustes"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactivo, comprobar aplicación"</string> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 6236f251f55d..1e5e49e0a143 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Soovituste laadimine"</string> <string name="controls_media_title" msgid="1746947284862928133">"Meedia"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Peidetakse praegune seanss."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Peida"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Jätka"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Seaded"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Passiivne, vaadake rakendust"</string> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 167a09c71ce3..38b2103d7973 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -1069,7 +1069,7 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Gomendioak kargatzen"</string> <string name="controls_media_title" msgid="1746947284862928133">"Multimedia-edukia"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Ezkutatu uneko saioa."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ezkutatu"</string> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Baztertu"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Berrekin"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Ezarpenak"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inaktibo; egiaztatu aplikazioa"</string> @@ -1085,5 +1085,5 @@ <string name="controls_menu_add" msgid="4447246119229920050">"Gehitu aukerak"</string> <string name="controls_menu_edit" msgid="890623986951347062">"Editatu aukerak"</string> <string name="one_handed_tutorial_title" msgid="6312198435090726656">"Esku bakarreko modua erabiltzea"</string> - <string name="one_handed_tutorial_description" msgid="7674850272340517174">"Ateratzeko, pasatu hatza pantailaren behealdetik gora edo sakatu aplikazioaren gainean, edonon"</string> + <string name="one_handed_tutorial_description" msgid="7674850272340517174">"Ateratzeko, pasatu hatza pantailaren behealdetik gora edo sakatu aplikazioaren gainaldea"</string> </resources> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 055505200cc2..d39d0c3d5027 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -1069,7 +1069,7 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"درحال بار کردن توصیهها"</string> <string name="controls_media_title" msgid="1746947284862928133">"رسانه"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"جلسه فعلی پنهان شود."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"پنهان کردن"</string> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"رد کردن"</string> <string name="controls_media_resume" msgid="1933520684481586053">"ازسرگیری"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"تنظیمات"</string> <string name="controls_error_timeout" msgid="794197289772728958">"غیرفعال، برنامه را بررسی کنید"</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index ec9bbc4a8929..fa076c4fc40e 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Ladataan suosituksia"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Piilota nykyinen käyttökerta."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Piilota"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Jatka"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Asetukset"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Epäaktiivinen, tarkista sovellus"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 6c5387f63eda..9c418f79a075 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Chargement des recommandations…"</string> <string name="controls_media_title" msgid="1746947284862928133">"Commandes multimédias"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Masquer la session en cours."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Masquer"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Reprendre"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Paramètres"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifiez l\'appli"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 3a2ae07bc64d..3e2f5fdbff1d 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Chargement des recommandations"</string> <string name="controls_media_title" msgid="1746947284862928133">"Multimédia"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Masquer la session en cours."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Masquer"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Reprendre"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Paramètres"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifier l\'appli"</string> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 25c7b4bfab59..9ecd75e80a4c 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendacións"</string> <string name="controls_media_title" msgid="1746947284862928133">"Contido multimedia"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Oculta a sesión actual."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Configuración"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Comproba a app"</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 17cc5a45aeb9..6e05a540a13e 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"સુઝાવ લોડ કરી રહ્યાં છીએ"</string> <string name="controls_media_title" msgid="1746947284862928133">"મીડિયા"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"હાલનું સત્ર છુપાવો."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"છુપાવો"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"ફરી શરૂ કરો"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"સેટિંગ"</string> <string name="controls_error_timeout" msgid="794197289772728958">"નિષ્ક્રિય, ઍપને ચેક કરો"</string> @@ -1084,8 +1085,6 @@ <string name="controls_added_tooltip" msgid="4842812921719153085">"નવા નિયંત્રણ જોવા માટે પાવર બટનને દબાવી રાખો"</string> <string name="controls_menu_add" msgid="4447246119229920050">"નિયંત્રણો ઉમેરો"</string> <string name="controls_menu_edit" msgid="890623986951347062">"નિયંત્રણોમાં ફેરફાર કરો"</string> - <!-- no translation found for one_handed_tutorial_title (6312198435090726656) --> - <skip /> - <!-- no translation found for one_handed_tutorial_description (7674850272340517174) --> - <skip /> + <string name="one_handed_tutorial_title" msgid="6312198435090726656">"એક-હાથે વાપરો મોડનો ઉપયોગ કરી રહ્યાં છીએ"</string> + <string name="one_handed_tutorial_description" msgid="7674850272340517174">"બહાર નીકળવા માટે, સ્ક્રીનની નીચેના ભાગથી ઉપરની તરફ સ્વાઇપ કરો અથવા ઍપના આઇકન પર ગમે ત્યાં ટૅપ કરો"</string> </resources> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 97ae7b6e8926..de4fc482a101 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -1071,7 +1071,7 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"सुझाव लोड हो रहे हैं"</string> <string name="controls_media_title" msgid="1746947284862928133">"मीडिया"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"इस मीडिया सेशन को छिपाएं."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"छिपाएं"</string> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"खारिज करें"</string> <string name="controls_media_resume" msgid="1933520684481586053">"फिर से शुरू करें"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिंग"</string> <string name="controls_error_timeout" msgid="794197289772728958">"काम नहीं कर रहा, ऐप जांचें"</string> @@ -1086,6 +1086,6 @@ <string name="controls_added_tooltip" msgid="4842812921719153085">"नए कंट्रोल देखने के लिए पावर बटन दबाकर रखें"</string> <string name="controls_menu_add" msgid="4447246119229920050">"कंट्राेल जोड़ें"</string> <string name="controls_menu_edit" msgid="890623986951347062">"कंट्रोल मेन्यू में बदलाव करें"</string> - <string name="one_handed_tutorial_title" msgid="6312198435090726656">"वन-हैंडेड मोड का इस्तेमाल करें"</string> + <string name="one_handed_tutorial_title" msgid="6312198435090726656">"वन-हैंडेड मोड का इस्तेमाल करना"</string> <string name="one_handed_tutorial_description" msgid="7674850272340517174">"इसे बंद करने के लिए, स्क्रीन के सबसे निचले हिस्से से ऊपर की ओर स्वाइप करें या ऐप्लिकेशन के आइकॉन के ऊपर कहीं भी टैप करें"</string> </resources> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 9e17735ef18d..4bebe79c3c44 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -1075,7 +1075,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavanje preporuka"</string> <string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Sakrij trenutačnu sesiju."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sakrij"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Postavke"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, provjerite aplik."</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 804587f9bdcd..42e251fb39de 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Javaslatok betöltése…"</string> <string name="controls_media_title" msgid="1746947284862928133">"Média"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Jelenlegi munkamenet elrejtése."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Elrejtés"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Folytatás"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Beállítások"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inaktív, ellenőrizze az appot"</string> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 08ef489901ee..e6b71395c42a 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Բեռնման խորհուրդներ"</string> <string name="controls_media_title" msgid="1746947284862928133">"Մեդիա"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Թաքցրեք ընթացիկ աշխատաշրջանը"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Թաքցնել"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Շարունակել"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Կարգավորումներ"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Ակտիվ չէ, ստուգեք հավելվածը"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index ba9eca3f0de9..fec4205ba7da 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Memuat rekomendasi"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Menyembunyikan sesi saat ini."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sembunyikan"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Lanjutkan"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Setelan"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Nonaktif, periksa aplikasi"</string> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 629581346d46..3a9e63ba9f1a 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Hleður tillögum"</string> <string name="controls_media_title" msgid="1746947284862928133">"Margmiðlunarefni"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Fela núverandi lotu."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Fela"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Halda áfram"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Stillingar"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Óvirkt, athugaðu forrit"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index ef862cb0f919..3eca501b103c 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Caricamento dei consigli"</string> <string name="controls_media_title" msgid="1746947284862928133">"Contenuti multimediali"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Nascondi la sessione attuale."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Nascondi"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Riprendi"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Impostazioni"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inattivo, controlla l\'app"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 358946d69472..e88c951cf19e 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -1081,7 +1081,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"בטעינת המלצות"</string> <string name="controls_media_title" msgid="1746947284862928133">"מדיה"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"הסתרת הסשן הנוכחי."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"הסתרה"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"המשך"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"הגדרות"</string> <string name="controls_error_timeout" msgid="794197289772728958">"לא פעיל, יש לבדוק את האפליקציה"</string> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 9cb872bf1fab..130f682daaf3 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"候補を読み込んでいます"</string> <string name="controls_media_title" msgid="1746947284862928133">"メディア"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"現在のセッションを非表示にします。"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"非表示"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"再開"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string> <string name="controls_error_timeout" msgid="794197289772728958">"無効: アプリをご確認ください"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index ef6ff128ed09..d050875c35ce 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"მიმდინარეობს რეკომენდაციების ჩატვირთვა"</string> <string name="controls_media_title" msgid="1746947284862928133">"მედია"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"დაიმალოს მიმდინარე სესია"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"დამალვა"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"გაგრძელება"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"პარამეტრები"</string> <string name="controls_error_timeout" msgid="794197289772728958">"არააქტიურია, გადაამოწმეთ აპი"</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index 08b1f6262f1f..36c726edb791 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Жүктеуге қатысты ұсыныстар"</string> <string name="controls_media_title" msgid="1746947284862928133">"Мультимедиа"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Ағымдағы сеансты жасыру"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Жасыру"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Жалғастыру"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Параметрлер"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Өшірулі. Қолданба тексеріңіз."</string> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 6d80ee47413c..9d87c583c007 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"កំពុងផ្ទុកការណែនាំ"</string> <string name="controls_media_title" msgid="1746947284862928133">"មេឌៀ"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"លាក់វគ្គបច្ចុប្បន្ន។"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"លាក់"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"បន្ត"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"ការកំណត់"</string> <string name="controls_error_timeout" msgid="794197289772728958">"អសកម្ម ពិនិត្យមើលកម្មវិធី"</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index db2086458286..901f024c5f71 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ಶಿಫಾರಸುಗಳು ಲೋಡ್ ಆಗುತ್ತಿವೆ"</string> <string name="controls_media_title" msgid="1746947284862928133">"ಮಾಧ್ಯಮ"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"ಪ್ರಸ್ತುತ ಸೆಶನ್ ಅನ್ನು ಮರೆಮಾಡಿ."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ಮರೆಮಾಡಿ"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"ಪುನರಾರಂಭಿಸಿ"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> <string name="controls_error_timeout" msgid="794197289772728958">"ನಿಷ್ಕ್ರಿಯ, ಆ್ಯಪ್ ಪರಿಶೀಲಿಸಿ"</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index b43eb410c46d..8a6415566676 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"추천 제어 기능 로드 중"</string> <string name="controls_media_title" msgid="1746947284862928133">"미디어"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"현재 세션을 숨깁니다."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"숨기기"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"다시 시작"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"설정"</string> <string name="controls_error_timeout" msgid="794197289772728958">"비활성. 앱을 확인하세요."</string> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 02e468a4f311..3cf41264a4d4 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Сунуштар жүктөлүүдө"</string> <string name="controls_media_title" msgid="1746947284862928133">"Медиа"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Учурдагы сеансты жашыруу."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Жашыруу"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Улантуу"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Жөндөөлөр"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Жигерсиз. Колдонмону текшериңиз"</string> diff --git a/packages/SystemUI/res/values-land-television/dimens.xml b/packages/SystemUI/res/values-land-television/dimens.xml index 499341c662b1..90fc652b05e9 100644 --- a/packages/SystemUI/res/values-land-television/dimens.xml +++ b/packages/SystemUI/res/values-land-television/dimens.xml @@ -17,5 +17,8 @@ <resources> <!-- Width of volume bar --> <dimen name="volume_dialog_row_width">252dp</dimen> - <dimen name="volume_dialog_tap_target_size">36dp</dimen> + <dimen name="tv_volume_dialog_bubble_size">36dp</dimen> + <dimen name="tv_volume_dialog_corner_radius">40dp</dimen> + <dimen name="tv_volume_dialog_row_padding">5dp</dimen> + <dimen name="tv_volume_number_text_size">16dp</dimen> </resources> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 030bdc1ae120..b1c5a5cd887e 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ກຳລັງໂຫຼດຄຳແນະນຳ"</string> <string name="controls_media_title" msgid="1746947284862928133">"ມີເດຍ"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"ເຊື່ອງເຊດຊັນປັດຈຸບັນ."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ເຊື່ອງ"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"ສືບຕໍ່"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"ການຕັ້ງຄ່າ"</string> <string name="controls_error_timeout" msgid="794197289772728958">"ບໍ່ເຮັດວຽກ, ກະລຸນາກວດສອບແອັບ"</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 6f487416b322..4e9b802f4916 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -1081,7 +1081,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Įkeliamos rekomendacijos"</string> <string name="controls_media_title" msgid="1746947284862928133">"Medija"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Slėpti dabartinį seansą."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Slėpti"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Tęsti"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Nustatymai"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Neaktyvu, patikrinkite progr."</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index bdea26a1a202..a4c4666fafe3 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -1075,7 +1075,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Notiek ieteikumu ielāde"</string> <string name="controls_media_title" msgid="1746947284862928133">"Multivide"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Paslēpiet pašreizējo sesiju."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Paslēpt"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Atsākt"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Iestatījumi"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Neaktīva, pārbaudiet lietotni"</string> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index c9f3777c6192..7e623ad5032f 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Се вчитуваат препораки"</string> <string name="controls_media_title" msgid="1746947284862928133">"Аудиовизуелни содржини"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Сокриј ја тековнава сесија."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Сокриј"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Продолжи"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Поставки"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Неактивна, провери апликација"</string> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index c968c2827437..35e642769981 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"നിർദ്ദേശങ്ങൾ ലോഡ് ചെയ്യുന്നു"</string> <string name="controls_media_title" msgid="1746947284862928133">"മീഡിയ"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"നിലവിലെ സെഷൻ മറയ്ക്കുക."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"മറയ്ക്കുക"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"പുനരാരംഭിക്കുക"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"ക്രമീകരണം"</string> <string name="controls_error_timeout" msgid="794197289772728958">"നിഷ്ക്രിയം, ആപ്പ് പരിശോധിക്കൂ"</string> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 9ce6779e9ae4..b4690d418480 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Зөвлөмжүүдийг ачаалж байна"</string> <string name="controls_media_title" msgid="1746947284862928133">"Медиа"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Одоогийн харилцан үйлдлийг нуугаарай."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Нуух"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Үргэлжлүүлэх"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Тохиргоо"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Идэвхгүй байна, аппыг шалгана уу"</string> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index d7126795089f..4ea965ad80fc 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"शिफारशी लोड करत आहे"</string> <string name="controls_media_title" msgid="1746947284862928133">"मीडिया"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"सध्याचे सेशन लपवा."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"लपवा"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"पुन्हा सुरू करा"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिंग्ज"</string> <string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय, ॲप तपासा"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 01e918ade0ee..38ee25c7f3e4 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Memuatkan cadangan"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Sembunyikan sesi semasa."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sembunyikan"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Sambung semula"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Tetapan"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Tidak aktif, semak apl"</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 23b0a06cca8f..150ed94eec38 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -1069,7 +1069,7 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"အကြံပြုချက်များ ဖွင့်နေသည်"</string> <string name="controls_media_title" msgid="1746947284862928133">"မီဒီယာ"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"လက်ရှိ စက်ရှင်ကို ဖျောက်ထားမည်။"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ဖျောက်ထားမည်"</string> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"ပယ်ရန်"</string> <string name="controls_media_resume" msgid="1933520684481586053">"ဆက်လုပ်ရန်"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"ဆက်တင်များ"</string> <string name="controls_error_timeout" msgid="794197289772728958">"ရပ်နေသည်၊ အက်ပ်ကို စစ်ဆေးပါ"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index b0a593fe42f9..d872a89880c9 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Laster inn anbefalinger"</string> <string name="controls_media_title" msgid="1746947284862928133">"Medier"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Skjul den nåværende økten."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skjul"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Gjenoppta"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Innstillinger"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Sjekk appen"</string> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index 09462cf3ffcb..1974e8088971 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -731,11 +731,11 @@ <string name="see_more_title" msgid="7409317011708185729">"थप हेर्नुहोस्"</string> <string name="appops_camera" msgid="5215967620896725715">"यो अनुप्रयोगले क्यामेराको प्रयोग गर्दै छ।"</string> <string name="appops_microphone" msgid="8805468338613070149">"यो अनुप्रयोगले माइक्रोफोनको प्रयोग गर्दै छ।"</string> - <string name="appops_overlay" msgid="4822261562576558490">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य अनुप्रयोगहरूमाथि प्रदर्शन गर्दै छ।"</string> + <string name="appops_overlay" msgid="4822261562576558490">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य एपमाथि प्रदर्शन गर्दै छ।"</string> <string name="appops_camera_mic" msgid="7032239823944420431">"यो अनुप्रयोगले माइक्रोफोन र क्यामेराको प्रयोग गर्दै छ।"</string> - <string name="appops_camera_overlay" msgid="6466845606058816484">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य अनुप्रयोगहरूमाथि प्रदर्शन गर्नुका साथै क्यामेराको प्रयोग गर्दै छ।"</string> - <string name="appops_mic_overlay" msgid="4609326508944233061">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य अनुप्रयोगहरूमाथि प्रदर्शन गर्नुका साथै माइक्रोफोनको प्रयोग गर्दै छ।"</string> - <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य अनुप्रयोगहरूमाथि प्रदर्शन गर्नुका साथै माइक्रोफोन र क्यामेराको प्रयोग गर्दै छ।"</string> + <string name="appops_camera_overlay" msgid="6466845606058816484">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य एपमाथि प्रदर्शन गर्नुका साथै क्यामेराको प्रयोग गर्दै छ।"</string> + <string name="appops_mic_overlay" msgid="4609326508944233061">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य एपमाथि प्रदर्शन गर्नुका साथै माइक्रोफोनको प्रयोग गर्दै छ।"</string> + <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य एपमाथि प्रदर्शन गर्नुका साथै माइक्रोफोन र क्यामेराको प्रयोग गर्दै छ।"</string> <string name="notification_appops_settings" msgid="5208974858340445174">"सेटिङहरू"</string> <string name="notification_appops_ok" msgid="2177609375872784124">"ठिक छ"</string> <string name="feedback_silenced" msgid="5382212321253328247">"सिस्टमले यो सूचना आउँदा बज्ने ध्वनि बन्द गरेको छ।"</string> @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"सिफारिसहरू लोड गर्दै"</string> <string name="controls_media_title" msgid="1746947284862928133">"मिडिया"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"हालको सत्र लुकाउनुहोस्।"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"लुकाउनुहोस्"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"सुचारु गर्नुहोस्"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिङ"</string> <string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय छ, एप जाँच गर्नु…"</string> @@ -1084,8 +1085,6 @@ <string name="controls_added_tooltip" msgid="4842812921719153085">"नयाँ नियन्त्रण सुविधाहरू हेर्न पावर बटन थिचिराख्नुहोस्"</string> <string name="controls_menu_add" msgid="4447246119229920050">"नियन्त्रण सुविधाहरू थप्नुहोस्"</string> <string name="controls_menu_edit" msgid="890623986951347062">"नियन्त्रण सुविधाहरू सम्पादन गर्नु…"</string> - <!-- no translation found for one_handed_tutorial_title (6312198435090726656) --> - <skip /> - <!-- no translation found for one_handed_tutorial_description (7674850272340517174) --> - <skip /> + <string name="one_handed_tutorial_title" msgid="6312198435090726656">"एक हाते मोड प्रयोग गरिँदै छ"</string> + <string name="one_handed_tutorial_description" msgid="7674850272340517174">"बाहिर निस्कन, स्क्रिनको पुछारबाट माथितिर स्वाइप गर्नुहोस् वा एपभन्दा माथि जुनसुकै ठाउँमा ट्याप गर्नुहोस्"</string> </resources> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 2385017a0df7..9da8afa4d698 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Aanbevelingen laden"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"De huidige sessie verbergen."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Verbergen"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Hervatten"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Instellingen"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactief, check de app"</string> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index d5c077b3ec1b..5b5cbc62fe21 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ସୁପାରିଶଗୁଡ଼ିକ ଲୋଡ୍ କରାଯାଉଛି"</string> <string name="controls_media_title" msgid="1746947284862928133">"ମିଡିଆ"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"ବର୍ତ୍ତମାନର ସେସନ୍ ଲୁଚାନ୍ତୁ।"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ଲୁଚାନ୍ତୁ"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"ପୁଣି ଆରମ୍ଭ କରନ୍ତୁ"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"ସେଟିଂସ୍"</string> <string name="controls_error_timeout" msgid="794197289772728958">"ନିଷ୍କ୍ରିୟ ଅଛି, ଆପ ଯାଞ୍ଚ କରନ୍ତୁ"</string> @@ -1084,8 +1085,6 @@ <string name="controls_added_tooltip" msgid="4842812921719153085">"ନୂଆ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ଦେଖିବା ପାଇଁ ପାୱାର ବଟନକୁ ଧରି ରଖନ୍ତୁ"</string> <string name="controls_menu_add" msgid="4447246119229920050">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଯୋଗ କରନ୍ତୁ"</string> <string name="controls_menu_edit" msgid="890623986951347062">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ସମ୍ପାଦନ କରନ୍ତୁ"</string> - <!-- no translation found for one_handed_tutorial_title (6312198435090726656) --> - <skip /> - <!-- no translation found for one_handed_tutorial_description (7674850272340517174) --> - <skip /> + <string name="one_handed_tutorial_title" msgid="6312198435090726656">"ଏକ-ହାତ ମୋଡ୍ ବ୍ୟବହାର କରି"</string> + <string name="one_handed_tutorial_description" msgid="7674850272340517174">"ବାହାରି ଯିବା ପାଇଁ, ତଳୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ କିମ୍ବା ଆପ୍ ଆଇକନର ଉପରେ ଯେ କୌଣସି ସ୍ଥାନରେ ଟାପ୍ କରନ୍ତୁ"</string> </resources> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 11567821397a..5c31ce71ef98 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ਸਿਫ਼ਾਰਸ਼ਾਂ ਲੋਡ ਹੋ ਰਹੀਆਂ ਹਨ"</string> <string name="controls_media_title" msgid="1746947284862928133">"ਮੀਡੀਆ"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"ਮੌਜੂਦਾ ਸੈਸ਼ਨ ਨੂੰ ਲੁਕਾਓ।"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ਲੁਕਾਓ"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"ਮੁੜ-ਚਾਲੂ ਕਰੋ"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"ਸੈਟਿੰਗਾਂ"</string> <string name="controls_error_timeout" msgid="794197289772728958">"ਅਕਿਰਿਆਸ਼ੀਲ, ਐਪ ਦੀ ਜਾਂਚ ਕਰੋ"</string> @@ -1084,8 +1085,6 @@ <string name="controls_added_tooltip" msgid="4842812921719153085">"ਨਵੇਂ ਕੰਟਰੋਲ ਦੇਖਣ ਲਈ ਪਾਵਰ ਬਟਨ ਦਬਾਈ ਰੱਖੋ"</string> <string name="controls_menu_add" msgid="4447246119229920050">"ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕਰੋ"</string> <string name="controls_menu_edit" msgid="890623986951347062">"ਕੰਟਰੋਲਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string> - <!-- no translation found for one_handed_tutorial_title (6312198435090726656) --> - <skip /> - <!-- no translation found for one_handed_tutorial_description (7674850272340517174) --> - <skip /> + <string name="one_handed_tutorial_title" msgid="6312198435090726656">"ਇੱਕ ਹੱਥ ਮੋਡ ਵਰਤਣਾ"</string> + <string name="one_handed_tutorial_description" msgid="7674850272340517174">"ਬਾਹਰ ਜਾਣ ਲਈ, ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ ਜਾਂ ਐਪ \'ਤੇ ਕਿਤੇ ਵੀ ਟੈਪ ਕਰੋ"</string> </resources> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 1f6effe431e7..b7ee75057626 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -1081,7 +1081,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Wczytuję rekomendacje"</string> <string name="controls_media_title" msgid="1746947284862928133">"Multimedia"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Ukryj bieżącą sesję."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ukryj"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Wznów"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Ustawienia"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Nieaktywny, sprawdź aplikację"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 14d7a84dab28..715b0e45faeb 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -1069,7 +1069,7 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregando recomendações"</string> <string name="controls_media_title" msgid="1746947284862928133">"Mídia"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Ocultar a sessão atual."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dispensar"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Configurações"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index a6f7f004f411..1a59de496c91 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -1069,7 +1069,7 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"A carregar recomendações…"</string> <string name="controls_media_title" msgid="1746947284862928133">"Multimédia"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Oculte a sessão atual."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignorar"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Definições"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inativa. Consulte a app."</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 14d7a84dab28..715b0e45faeb 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -1069,7 +1069,7 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregando recomendações"</string> <string name="controls_media_title" msgid="1746947284862928133">"Mídia"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Ocultar a sessão atual."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dispensar"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Configurações"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 0f15cfcd23f6..49c3ba0c2cd8 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -1075,7 +1075,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Se încarcă recomandările"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Ascunde sesiunea actuală."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ascunde"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Reia"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Setări"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inactiv, verificați aplicația"</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 6196f88a7bfb..7fb456d5f425 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -1081,7 +1081,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Загрузка рекомендаций…"</string> <string name="controls_media_title" msgid="1746947284862928133">"Медиа"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Скрыть текущий сеанс?"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Скрыть"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Возобновить"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Настройки"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Нет ответа. Проверьте приложение."</string> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index 8aca9f4e0dbd..1cd1ceb21c97 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -1069,7 +1069,7 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"නිර්දේශ පූරණය කරමින්"</string> <string name="controls_media_title" msgid="1746947284862928133">"මාධ්ය"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"වත්මන් සැසිය සඟවන්න."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"සඟවන්න"</string> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"ඉවත ලන්න"</string> <string name="controls_media_resume" msgid="1933520684481586053">"නැවත පටන් ගන්න"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"සැකසීම්"</string> <string name="controls_error_timeout" msgid="794197289772728958">"අක්රියයි, යෙදුම පරීක්ෂා කරන්න"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 45ee562b374c..9d7e7d1cd27c 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -1081,7 +1081,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Načítavajú sa odporúčania"</string> <string name="controls_media_title" msgid="1746947284862928133">"Médiá"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Skryť aktuálnu reláciu."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skryť"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Pokračovať"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavenia"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Neaktívne, preverte aplikáciu"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index c7ad8ab92da3..ecbf1d905e5b 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -1081,7 +1081,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Nalaganje priporočil"</string> <string name="controls_media_title" msgid="1746947284862928133">"Predstavnost"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Skrije trenutno sejo."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skrij"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Nadaljuj"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavitve"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, poglejte aplikacijo"</string> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 3e0aecc16d4e..70245b875726 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Po ngarkon rekomandimet"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Fshih sesionin aktual."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Fshih"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Vazhdo"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Cilësimet"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Joaktive, kontrollo aplikacionin"</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 985041b3b24d..1d02ca6ab455 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -1075,7 +1075,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Учитавају се препоруке"</string> <string name="controls_media_title" msgid="1746947284862928133">"Медији"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Сакријте актуелну сесију."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Сакриј"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Настави"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Подешавања"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Неактивно. Видите апликацију"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 2018a383b5ed..7a7448be16c5 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Rekommendationer läses in"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Dölj den aktuella sessionen."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Dölj"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Återuppta"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Inställningar"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv, kolla appen"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 6eecc0e402fa..b8d95fcd0c1a 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Inapakia mapendekezo"</string> <string name="controls_media_title" msgid="1746947284862928133">"Maudhui"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Ficha kipindi cha sasa."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ficha"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Endelea"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Mipangilio"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Haitumiki, angalia programu"</string> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index a05e0e735620..60c1cf9dcac0 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"பரிந்துரைகளை ஏற்றுகிறது"</string> <string name="controls_media_title" msgid="1746947284862928133">"மீடியா"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"இந்த அமர்வை மறையுங்கள்."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"மறை"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"தொடர்க"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"அமைப்புகள்"</string> <string name="controls_error_timeout" msgid="794197289772728958">"செயலில் இல்லை , சரிபார்க்கவும்"</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 7d76abd0f20f..6cfe03d95023 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"సిఫార్సులు లోడ్ అవుతున్నాయి"</string> <string name="controls_media_title" msgid="1746947284862928133">"మీడియా"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"ప్రస్తుత సెషన్ను దాచు."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"దాచు"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"కొనసాగించండి"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"సెట్టింగ్లు"</string> <string name="controls_error_timeout" msgid="794197289772728958">"ఇన్యాక్టివ్, యాప్ చెక్ చేయండి"</string> diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml index 1696aab66148..7b1479acc35e 100644 --- a/packages/SystemUI/res/values-television/config.xml +++ b/packages/SystemUI/res/values-television/config.xml @@ -43,4 +43,7 @@ <item>com.android.systemui.toast.ToastUI</item> <item>com.android.systemui.onehanded.OneHandedUI</item> </string-array> + + <!-- Show a separate icon for low and high volume on the volume dialog --> + <bool name="config_showLowMediaVolumeIcon">true</bool> </resources> diff --git a/packages/SystemUI/res/values-television/styles.xml b/packages/SystemUI/res/values-television/styles.xml index b01c5d88e3b3..4cf7034a29bf 100644 --- a/packages/SystemUI/res/values-television/styles.xml +++ b/packages/SystemUI/res/values-television/styles.xml @@ -22,4 +22,8 @@ <item name="android:windowEnterAnimation">@null</item> <item name="android:windowExitAnimation">@null</item> </style> + + <style name="volume_dialog_theme" parent="qs_theme"> + <item name="android:colorAccent">@color/tv_volume_dialog_accent</item> + </style> </resources> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 765c22424e89..a2c1127df5ca 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"กำลังโหลดคำแนะนำ"</string> <string name="controls_media_title" msgid="1746947284862928133">"สื่อ"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"ซ่อนเซสชันปัจจุบัน"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ซ่อน"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"เล่นต่อ"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"การตั้งค่า"</string> <string name="controls_error_timeout" msgid="794197289772728958">"ไม่มีการใช้งาน โปรดตรวจสอบแอป"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index c2cae9024a60..e5f0532b0e7b 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Nilo-load ang rekomendasyon"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Itago ang kasalukuyang session."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Itago"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Ituloy"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Mga Setting"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Hindi aktibo, tingnan ang app"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 74b44f2079c6..4943e2d03920 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Öneriler yükleniyor"</string> <string name="controls_media_title" msgid="1746947284862928133">"Medya"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Mevcut oturumu gizle."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Gizle"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Devam ettir"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Ayarlar"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Devre dışı, uygulamaya bakın"</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 38c331ade344..447912e08835 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -1081,7 +1081,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Завантаження рекомендацій"</string> <string name="controls_media_title" msgid="1746947284862928133">"Медіа"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Приховати поточний сеанс."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Приховати"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Відновити"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Налаштування"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, перейдіть у додаток"</string> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 69ddabbe94ac..20b551882344 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"تجاویز لوڈ ہو رہی ہیں"</string> <string name="controls_media_title" msgid="1746947284862928133">"میڈیا"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"موجودہ سیشن چھپائیں۔"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"چھپائیں"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"دوبارہ شروع کریں"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"ترتیبات"</string> <string name="controls_error_timeout" msgid="794197289772728958">"غیر فعال، ایپ چیک کریں"</string> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index ed704b0f5597..cf1da7508052 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -227,7 +227,7 @@ <string name="data_connection_roaming" msgid="375650836665414797">"Rouming"</string> <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string> <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string> - <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM karta solinmagan."</string> + <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM kartasiz."</string> <string name="accessibility_cell_data" msgid="172950885786007392">"Mobil internet"</string> <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobil internet yoniq"</string> <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobil internet yoqilmagan"</string> @@ -1069,7 +1069,7 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Tavsiyalar yuklanmoqda"</string> <string name="controls_media_title" msgid="1746947284862928133">"Media"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Joriy seans berkitilsin."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Berkitish"</string> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Yopish"</string> <string name="controls_media_resume" msgid="1933520684481586053">"Davom etish"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Sozlamalar"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Nofaol. Ilovani tekshiring"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 5cc209941771..a12a08d0a1e6 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Đang tải các đề xuất"</string> <string name="controls_media_title" msgid="1746947284862928133">"Nội dung nghe nhìn"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Ẩn phiên hiện tại."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ẩn"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Tiếp tục"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Cài đặt"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Không hoạt động, hãy kiểm tra ứng dụng"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index f670bf682b64..3382365b7ccb 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在加载推荐内容"</string> <string name="controls_media_title" msgid="1746947284862928133">"媒体"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"隐藏当前会话。"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"隐藏"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"继续播放"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"设置"</string> <string name="controls_error_timeout" msgid="794197289772728958">"无效,请检查应用"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 2e26d6153a8f..1d55ca22a43f 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在載入建議"</string> <string name="controls_media_title" msgid="1746947284862928133">"媒體"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"隱藏目前的工作階段。"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"隱藏"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"繼續播放"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string> <string name="controls_error_timeout" msgid="794197289772728958">"已停用,請檢查應用程式"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 0049d2ec1f56..e62c164684b3 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在載入建議控制項"</string> <string name="controls_media_title" msgid="1746947284862928133">"媒體"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"隱藏目前的工作階段。"</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"隱藏"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"繼續播放"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string> <string name="controls_error_timeout" msgid="794197289772728958">"無效,請查看應用程式"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index c8c99b1c18c1..bd7391203dd8 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -1069,7 +1069,8 @@ <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Ilayisha izincomo"</string> <string name="controls_media_title" msgid="1746947284862928133">"Imidiya"</string> <string name="controls_media_close_session" msgid="3957093425905475065">"Fihla iseshini yamanje."</string> - <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Fihla"</string> + <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> + <skip /> <string name="controls_media_resume" msgid="1933520684481586053">"Qalisa kabusha"</string> <string name="controls_media_settings_button" msgid="5815790345117172504">"Izilungiselelo"</string> <string name="controls_error_timeout" msgid="794197289772728958">"Akusebenzi, hlola uhlelo lokusebenza"</string> diff --git a/packages/SystemUI/res/values/colors_tv.xml b/packages/SystemUI/res/values/colors_tv.xml index c92762c017f4..cb49918e4e3f 100644 --- a/packages/SystemUI/res/values/colors_tv.xml +++ b/packages/SystemUI/res/values/colors_tv.xml @@ -28,4 +28,7 @@ <color name="tv_audio_recording_indicator_stroke">#33FFFFFF</color> <color name="red">#FFCC0000</color> + <color name="tv_volume_dialog_background">#E61F232B</color> + <color name="tv_volume_dialog_circle">#08FFFFFF</color> + <color name="tv_volume_dialog_accent">#FFDADCE0</color> </resources> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index fba43a628387..17ba7c99dc0c 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -574,4 +574,6 @@ <!-- Animation duration for translating of one handed when trigger / dismiss. --> <integer name="config_one_handed_translate_animation_duration">150</integer> + <!-- Show a separate icon for low and high volume on the volume dialog --> + <bool name="config_showLowMediaVolumeIcon">false</bool> </resources> diff --git a/packages/SystemUI/res/values/donottranslate.xml b/packages/SystemUI/res/values/donottranslate.xml index a1c52e55082a..f05be066d2e2 100644 --- a/packages/SystemUI/res/values/donottranslate.xml +++ b/packages/SystemUI/res/values/donottranslate.xml @@ -21,5 +21,5 @@ <string name="system_ui_date_pattern" translatable="false">@*android:string/system_ui_date_pattern</string> <!-- Date format for the always on display. --> - <item type="string" name="system_ui_aod_date_pattern" translatable="false">@*android:string/system_ui_date_pattern</item> + <item type="string" name="system_ui_aod_date_pattern" translatable="false">EEEMMMd</item> </resources> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 9e5b94ee855c..ee07e613a0c5 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -387,6 +387,9 @@ <item name="android:homeAsUpIndicator">@drawable/ic_arrow_back</item> </style> + <!-- Overridden by values-television/styles.xml with tv-specific settings --> + <style name="volume_dialog_theme" parent="qs_theme"/> + <style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault.Light"> <item name="android:colorAccent">@color/remote_input_accent</item> </style> diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java index 816bcf8f274b..d5f74a86fd94 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java @@ -53,8 +53,8 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall ActivityInfo.CONFIG_DENSITY | ActivityInfo.CONFIG_ORIENTATION; @VisibleForTesting - protected WindowMagnificationController mWindowMagnificationController; - protected final ModeSwitchesController mModeSwitchesController; + protected WindowMagnificationAnimationController mWindowMagnificationAnimationController; + private final ModeSwitchesController mModeSwitchesController; private final Handler mHandler; private final AccessibilityManager mAccessibilityManager; private final CommandQueue mCommandQueue; @@ -72,6 +72,11 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall Context.ACCESSIBILITY_SERVICE); mCommandQueue = commandQueue; mModeSwitchesController = modeSwitchesController; + final WindowMagnificationController controller = new WindowMagnificationController(mContext, + mHandler, new SfVsyncFrameCallbackProvider(), null, + new SurfaceControl.Transaction(), this); + mWindowMagnificationAnimationController = new WindowMagnificationAnimationController( + mContext, controller); } @Override @@ -81,9 +86,7 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall return; } mLastConfiguration.setTo(newConfig); - if (mWindowMagnificationController != null) { - mWindowMagnificationController.onConfigurationChanged(configDiff); - } + mWindowMagnificationAnimationController.onConfigurationChanged(configDiff); if (mModeSwitchesController != null) { mModeSwitchesController.onConfigurationChanged(configDiff); } @@ -97,39 +100,25 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall @MainThread void enableWindowMagnification(int displayId, float scale, float centerX, float centerY) { //TODO: b/144080869 support multi-display. - if (mWindowMagnificationController == null) { - mWindowMagnificationController = new WindowMagnificationController(mContext, - mHandler, - new SfVsyncFrameCallbackProvider(), - null, new SurfaceControl.Transaction(), - this); - } - mWindowMagnificationController.enableWindowMagnification(scale, centerX, centerY); + mWindowMagnificationAnimationController.enableWindowMagnification(scale, centerX, centerY); } @MainThread void setScale(int displayId, float scale) { //TODO: b/144080869 support multi-display. - if (mWindowMagnificationController != null) { - mWindowMagnificationController.setScale(scale); - } + mWindowMagnificationAnimationController.setScale(scale); } @MainThread void moveWindowMagnifier(int displayId, float offsetX, float offsetY) { //TODO: b/144080869 support multi-display. - if (mWindowMagnificationController != null) { - mWindowMagnificationController.moveWindowMagnifier(offsetX, offsetY); - } + mWindowMagnificationAnimationController.moveWindowMagnifier(offsetX, offsetY); } @MainThread void disableWindowMagnification(int displayId) { //TODO: b/144080869 support multi-display. - if (mWindowMagnificationController != null) { - mWindowMagnificationController.deleteWindowMagnification(); - } - mWindowMagnificationController = null; + mWindowMagnificationAnimationController.deleteWindowMagnification(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java new file mode 100644 index 000000000000..ae51623f3dc2 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2020 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.systemui.accessibility; + +import android.animation.Animator; +import android.animation.ValueAnimator; +import android.annotation.IntDef; +import android.content.Context; +import android.content.res.Resources; +import android.util.Log; +import android.view.animation.AccelerateInterpolator; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.R; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Provides same functionality of {@link WindowMagnificationController}. Some methods run with + * the animation. + */ +class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUpdateListener, + Animator.AnimatorListener { + + private static final String TAG = "WindowMagnificationBridge"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + @Retention(RetentionPolicy.SOURCE) + @IntDef({STATE_DISABLED, STATE_ENABLED, STATE_DISABLING, STATE_ENABLING}) + @interface MagnificationState {} + + //The window magnification is disabled. + private static final int STATE_DISABLED = 0; + //The window magnification is enabled. + private static final int STATE_ENABLED = 1; + //The window magnification is going to be disabled when the animation is end. + private static final int STATE_DISABLING = 2; + //The animation is running for enabling the window magnification. + private static final int STATE_ENABLING = 3; + + private final WindowMagnificationController mController; + private final ValueAnimator mValueAnimator; + private final AnimationSpec mStartSpec = new AnimationSpec(); + private final AnimationSpec mEndSpec = new AnimationSpec(); + private final Context mContext; + + @MagnificationState + private int mState = STATE_DISABLED; + + WindowMagnificationAnimationController( + Context context, WindowMagnificationController controller) { + this(context, controller, newValueAnimator(context.getResources())); + } + + @VisibleForTesting + WindowMagnificationAnimationController(Context context, + WindowMagnificationController controller, ValueAnimator valueAnimator) { + mContext = context; + mController = controller; + mValueAnimator = valueAnimator; + mValueAnimator.addUpdateListener(this); + mValueAnimator.addListener(this); + } + + /** + * Wraps {@link WindowMagnificationController#enableWindowMagnification(float, float, float)} + * with transition animation. If the window magnification is not enabled, the scale will start + * from 1.0 and the center won't be changed during the animation. If {@link #mState} is + * {@code STATE_DISABLING}, the animation runs in reverse. + * + * @param scale the target scale, or {@link Float#NaN} to leave unchanged. + * @param centerX the screen-relative X coordinate around which to center, + * or {@link Float#NaN} to leave unchanged. + * @param centerY the screen-relative Y coordinate around which to center, + * or {@link Float#NaN} to leave unchanged. + * + * @see #onAnimationUpdate(ValueAnimator) + */ + void enableWindowMagnification(float scale, float centerX, float centerY) { + if (mState == STATE_ENABLING) { + mValueAnimator.cancel(); + } + setupEnableAnimationSpecs(scale, centerX, centerY); + + if (mEndSpec.equals(mStartSpec)) { + setState(STATE_ENABLED); + } else { + if (mState == STATE_DISABLING) { + mValueAnimator.reverse(); + } else { + mValueAnimator.start(); + } + setState(STATE_ENABLING); + } + } + + private void setupEnableAnimationSpecs(float scale, float centerX, float centerY) { + final float currentScale = mController.getScale(); + final float currentCenterX = mController.getCenterX(); + final float currentCenterY = mController.getCenterY(); + + if (mState == STATE_DISABLED) { + //We don't need to offset the center during the animation. + mStartSpec.set(/* scale*/ 1.0f, centerX, centerY); + mEndSpec.set(Float.isNaN(scale) ? mContext.getResources().getInteger( + R.integer.magnification_default_scale) : scale, centerX, centerY); + } else { + mStartSpec.set(currentScale, currentCenterX, currentCenterY); + mEndSpec.set(Float.isNaN(scale) ? currentScale : scale, + Float.isNaN(centerX) ? currentCenterX : centerX, + Float.isNaN(centerY) ? currentCenterY : centerY); + } + if (DEBUG) { + Log.d(TAG, "SetupEnableAnimationSpecs : mStartSpec = " + mStartSpec + ", endSpec = " + + mEndSpec); + } + } + + /** + * Wraps {@link WindowMagnificationController#setScale(float)}. If the animation is + * running, it has no effect. + */ + void setScale(float scale) { + if (mValueAnimator.isRunning()) { + return; + } + mController.setScale(scale); + } + + /** + * Wraps {@link WindowMagnificationController#deleteWindowMagnification()}} with transition + * animation. If the window magnification is enabling, it runs the animation in reverse. + */ + void deleteWindowMagnification() { + if (mState == STATE_DISABLED || mState == STATE_DISABLING) { + return; + } + mStartSpec.set(/* scale*/ 1.0f, Float.NaN, Float.NaN); + mEndSpec.set(/* scale*/ mController.getScale(), Float.NaN, Float.NaN); + + mValueAnimator.reverse(); + setState(STATE_DISABLING); + } + + /** + * Wraps {@link WindowMagnificationController#moveWindowMagnifier(float, float)}. If the + * animation is running, it has no effect. + * @param offsetX the amount in pixels to offset the window magnifier in the X direction, in + * current screen pixels. + * @param offsetY the amount in pixels to offset the window magnifier in the Y direction, in + * current screen pixels. + */ + void moveWindowMagnifier(float offsetX, float offsetY) { + if (mValueAnimator.isRunning()) { + return; + } + mController.moveWindowMagnifier(offsetX, offsetY); + } + + void onConfigurationChanged(int configDiff) { + mController.onConfigurationChanged(configDiff); + } + + private void setState(@MagnificationState int state) { + if (DEBUG) { + Log.d(TAG, "setState from " + mState + " to " + state); + } + mState = state; + } + + @Override + public void onAnimationStart(Animator animation) { + } + + @Override + public void onAnimationEnd(Animator animation) { + if (mState == STATE_DISABLING) { + mController.deleteWindowMagnification(); + setState(STATE_DISABLED); + } else if (mState == STATE_ENABLING) { + setState(STATE_ENABLED); + } else { + Log.w(TAG, "onAnimationEnd unexpected state:" + mState); + } + } + + @Override + public void onAnimationCancel(Animator animation) { + } + + @Override + public void onAnimationRepeat(Animator animation) { + } + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + final float fract = animation.getAnimatedFraction(); + final float sentScale = mStartSpec.mScale + (mEndSpec.mScale - mStartSpec.mScale) * fract; + final float centerX = + mStartSpec.mCenterX + (mEndSpec.mCenterX - mStartSpec.mCenterX) * fract; + final float centerY = + mStartSpec.mCenterY + (mEndSpec.mCenterY - mStartSpec.mCenterY) * fract; + mController.enableWindowMagnification(sentScale, centerX, centerY); + } + + private static ValueAnimator newValueAnimator(Resources resources) { + final ValueAnimator valueAnimator = new ValueAnimator(); + valueAnimator.setDuration( + resources.getInteger(com.android.internal.R.integer.config_longAnimTime)); + valueAnimator.setInterpolator(new AccelerateInterpolator(2.5f)); + valueAnimator.setFloatValues(0.0f, 1.0f); + return valueAnimator; + } + + private static class AnimationSpec { + private float mScale = Float.NaN; + private float mCenterX = Float.NaN; + private float mCenterY = Float.NaN; + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (other == null || getClass() != other.getClass()) { + return false; + } + + final AnimationSpec s = (AnimationSpec) other; + return mScale == s.mScale && mCenterX == s.mCenterX && mCenterY == s.mCenterY; + } + + @Override + public int hashCode() { + int result = (mScale != +0.0f ? Float.floatToIntBits(mScale) : 0); + result = 31 * result + (mCenterX != +0.0f ? Float.floatToIntBits(mCenterX) : 0); + result = 31 * result + (mCenterY != +0.0f ? Float.floatToIntBits(mCenterY) : 0); + return result; + } + + void set(float scale, float centerX, float centerY) { + mScale = scale; + mCenterX = centerX; + mCenterY = centerY; + } + + @Override + public String toString() { + return "AnimationSpec{" + + "mScale=" + mScale + + ", mCenterX=" + mCenterX + + ", mCenterY=" + mCenterY + + '}'; + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index 798b751c03ee..494a0f64cea4 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -150,7 +150,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mMirrorViewGeometryVsyncCallback = l -> { - if (mMirrorView != null && mMirrorSurface != null) { + if (isWindowVisible() && mMirrorSurface != null) { calculateSourceBounds(mMagnificationFrame, mScale); // The final destination for the magnification surface should be at 0,0 // since the ViewRootImpl's position will change @@ -203,13 +203,13 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold * @param configDiff a bit mask of the differences between the configurations */ void onConfigurationChanged(int configDiff) { + if (!isWindowVisible()) { + return; + } if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0) { updateDimensions(); - // TODO(b/145780606): update toggle button UI. - if (mMirrorView != null) { - mWm.removeView(mMirrorView); - createMirrorWindow(); - } + mWm.removeView(mMirrorView); + createMirrorWindow(); } else if ((configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0) { onRotate(); } @@ -502,7 +502,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold /** * Enables window magnification with specified parameters. * - * @param scale the target scale + * @param scale the target scale, or {@link Float#NaN} to leave unchanged * @param centerX the screen-relative X coordinate around which to center, * or {@link Float#NaN} to leave unchanged. * @param centerY the screen-relative Y coordinate around which to center, @@ -513,10 +513,10 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold : centerX - mMagnificationFrame.exactCenterX(); final float offsetY = Float.isNaN(centerY) ? 0 : centerY - mMagnificationFrame.exactCenterY(); - mScale = scale; + mScale = Float.isNaN(scale) ? mScale : scale; setMagnificationFrameBoundary(); updateMagnificationFramePosition((int) offsetX, (int) offsetY); - if (mMirrorView == null) { + if (!isWindowVisible()) { createMirrorWindow(); showControls(); } else { @@ -527,10 +527,10 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold /** * Sets the scale of the magnified region if it's visible. * - * @param scale the target scale + * @param scale the target scale, or {@link Float#NaN} to leave unchanged */ void setScale(float scale) { - if (mMirrorView == null || mScale == scale) { + if (!isWindowVisible() || mScale == scale) { return; } enableWindowMagnification(scale, Float.NaN, Float.NaN); @@ -552,4 +552,35 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold modifyWindowMagnification(mTransaction); } } + + /** + * Gets the scale. + * @return {@link Float#NaN} if the window is invisible. + */ + float getScale() { + return isWindowVisible() ? mScale : Float.NaN; + } + + /** + * Returns the screen-relative X coordinate of the center of the magnified bounds. + * + * @return the X coordinate. {@link Float#NaN} if the window is invisible. + */ + float getCenterX() { + return isWindowVisible() ? mMagnificationFrame.exactCenterX() : Float.NaN; + } + + /** + * Returns the screen-relative Y coordinate of the center of the magnified bounds. + * + * @return the Y coordinate. {@link Float#NaN} if the window is invisible. + */ + float getCenterY() { + return isWindowVisible() ? mMagnificationFrame.exactCenterY() : Float.NaN; + } + + //The window is visible when it is existed. + private boolean isWindowVisible() { + return mMirrorView != null; + } } diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt b/packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt index 8b953fa46441..be089b12a95d 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt @@ -21,7 +21,7 @@ import com.android.internal.logging.UiEventLogger enum class AssistantSessionEvent(private val id: Int) : UiEventLogger.UiEventEnum { @UiEvent(doc = "Unknown assistant session event") - ASSISTANT_SESSION_UNKNOWN(523), + ASSISTANT_SESSION_UNKNOWN(0), @UiEvent(doc = "Assistant session dismissed due to timeout") ASSISTANT_SESSION_TIMEOUT_DISMISS(524), diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index fce545b421d5..f774358b69fb 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -38,6 +38,7 @@ import com.android.systemui.statusbar.notification.collection.inflation.Notifica import com.android.systemui.statusbar.notification.people.PeopleHubModule; import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent; import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent; +import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent; import com.android.systemui.statusbar.phone.KeyguardLiftController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; @@ -72,7 +73,8 @@ import dagger.Provides; subcomponents = {StatusBarComponent.class, NotificationRowComponent.class, DozeComponent.class, - ExpandableNotificationRowComponent.class}) + ExpandableNotificationRowComponent.class, + NotificationShelfComponent.class}) public abstract class SystemUIModule { @Binds diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt index 8a51c8515852..e77e499223aa 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt @@ -44,6 +44,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dump.DumpManager +import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.notification.MediaNotificationProcessor import com.android.systemui.statusbar.notification.row.HybridGroupManager import com.android.systemui.util.Assert @@ -97,6 +98,7 @@ class MediaDataManager( dumpManager: DumpManager, mediaTimeoutListener: MediaTimeoutListener, mediaResumeListener: MediaResumeListener, + private val activityStarter: ActivityStarter, private var useMediaResumption: Boolean, private val useQsMediaPlayer: Boolean ) : Dumpable { @@ -113,10 +115,11 @@ class MediaDataManager( dumpManager: DumpManager, broadcastDispatcher: BroadcastDispatcher, mediaTimeoutListener: MediaTimeoutListener, - mediaResumeListener: MediaResumeListener + mediaResumeListener: MediaResumeListener, + activityStarter: ActivityStarter ) : this(context, backgroundExecutor, foregroundExecutor, mediaControllerFactory, broadcastDispatcher, dumpManager, mediaTimeoutListener, mediaResumeListener, - Utils.useMediaResumption(context), Utils.useQsMediaPlayer(context)) + activityStarter, Utils.useMediaResumption(context), Utils.useQsMediaPlayer(context)) private val appChangeReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { @@ -403,10 +406,13 @@ class MediaDataManager( } val runnable = if (action.actionIntent != null) { Runnable { - try { - action.actionIntent.send() - } catch (e: PendingIntent.CanceledException) { - Log.d(TAG, "Intent canceled", e) + if (action.isAuthenticationRequired()) { + activityStarter.dismissKeyguardThenExecute ({ + var result = sendPendingIntent(action.actionIntent) + result + }, {}, true) + } else { + sendPendingIntent(action.actionIntent) } } } else { @@ -449,6 +455,15 @@ class MediaDataManager( return null } + private fun sendPendingIntent(intent: PendingIntent): Boolean { + return try { + intent.send() + true + } catch (e: PendingIntent.CanceledException) { + Log.d(TAG, "Intent canceled", e) + false + } + } /** * Load a bitmap from a URI * @param uri the uri to load diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java index 01670285c0f4..f1c8b0cf0e42 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java @@ -186,20 +186,23 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio private class PipManagerPinnedStackListener extends PinnedStackListener { @Override public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { - if (mState == STATE_PIP) { - if (mImeVisible != imeVisible) { - if (imeVisible) { - // Save the IME height adjustment, and offset to not occlude the IME - mPipBounds.offset(0, -imeHeight); - mImeHeightAdjustment = imeHeight; - } else { - // Apply the inverse adjustment when the IME is hidden - mPipBounds.offset(0, mImeHeightAdjustment); + mHandler.post(() -> { + mPipBoundsHandler.onImeVisibilityChanged(imeVisible, imeHeight); + if (mState == STATE_PIP) { + if (mImeVisible != imeVisible) { + if (imeVisible) { + // Save the IME height adjustment, and offset to not occlude the IME + mPipBounds.offset(0, -imeHeight); + mImeHeightAdjustment = imeHeight; + } else { + // Apply the inverse adjustment when the IME is hidden + mPipBounds.offset(0, mImeHeightAdjustment); + } + mImeVisible = imeVisible; + resizePinnedStack(STATE_PIP); } - mImeVisible = imeVisible; - resizePinnedStack(STATE_PIP); } - } + }); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index d2aaaede3f4b..255513a31c75 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -14,6 +14,7 @@ package com.android.systemui.qs.tileimpl; +import static androidx.lifecycle.Lifecycle.State.CREATED; import static androidx.lifecycle.Lifecycle.State.DESTROYED; import static androidx.lifecycle.Lifecycle.State.RESUMED; import static androidx.lifecycle.Lifecycle.State.STARTED; @@ -173,6 +174,7 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy mState = newTileState(); mTmpState = newTileState(); + mUiHandler.post(() -> mLifecycle.setCurrentState(CREATED)); } protected final void resetStates() { @@ -453,6 +455,9 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy if (DEBUG) Log.d(TAG, "handleSetListening true"); handleSetListening(listening); mUiHandler.post(() -> { + // This tile has been destroyed, the state should not change anymore and we + // should not refresh it anymore. + if (mLifecycle.getCurrentState().equals(DESTROYED)) return; mLifecycle.setCurrentState(RESUMED); refreshState(); // Ensure we get at least one refresh after listening. }); @@ -461,7 +466,11 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy if (mListeners.remove(listener) && mListeners.size() == 0) { if (DEBUG) Log.d(TAG, "handleSetListening false"); handleSetListening(listening); - mUiHandler.post(() -> mLifecycle.setCurrentState(STARTED)); + mUiHandler.post(() -> { + // This tile has been destroyed, the state should not change anymore. + if (mLifecycle.getCurrentState().equals(DESTROYED)) return; + mLifecycle.setCurrentState(STARTED); + }); } } updateIsFullQs(); @@ -488,11 +497,14 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy mQSLogger.logTileDestroyed(mTileSpec, "Handle destroy"); if (mListeners.size() != 0) { handleSetListening(false); + mListeners.clear(); } mCallbacks.clear(); mHandler.removeCallbacksAndMessages(null); // This will force it to be removed from all controllers that may have it registered. - mLifecycle.setCurrentState(DESTROYED); + mUiHandler.post(() -> { + mLifecycle.setCurrentState(DESTROYED); + }); } protected void checkIfRestrictionEnforcedByAdminOnly(State state, String userRestriction) { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java index c53523032353..6747281ac437 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java @@ -50,6 +50,7 @@ import android.graphics.drawable.LayerDrawable; import android.media.MediaActionSound; import android.net.Uri; import android.os.Handler; +import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.RemoteException; @@ -556,11 +557,18 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset private void takeScreenshotInternal(Consumer<Uri> finisher, Rect crop) { // copy the input Rect, since SurfaceControl.screenshot can mutate it Rect screenRect = new Rect(crop); - int rot = mDisplay.getRotation(); int width = crop.width(); int height = crop.height(); - saveScreenshot(SurfaceControl.screenshot(crop, width, height, rot), finisher, screenRect, - Insets.NONE, true); + final IBinder displayToken = SurfaceControl.getInternalDisplayToken(); + final SurfaceControl.DisplayCaptureArgs captureArgs = + new SurfaceControl.DisplayCaptureArgs.Builder(displayToken) + .setSourceCrop(crop) + .setSize(width, height) + .build(); + final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer = + SurfaceControl.captureDisplay(captureArgs); + final Bitmap screenshot = screenshotBuffer == null ? null : screenshotBuffer.asBitmap(); + saveScreenshot(screenshot, finisher, screenRect, Insets.NONE, true); } private void saveScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java index 6b023c07b1a6..95867957f648 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java @@ -161,7 +161,9 @@ public class NotificationRemoteInputManager implements Dumpable { ActivityManager.getService().resumeAppSwitches(); } catch (RemoteException e) { } - return mCallback.handleRemoteViewClick(view, pendingIntent, () -> { + Notification.Action action = getActionFromView(view, entry, pendingIntent); + return mCallback.handleRemoteViewClick(view, pendingIntent, + action == null ? false : action.isAuthenticationRequired(), () -> { Pair<Intent, ActivityOptions> options = response.getLaunchOptions(view); options.second.setLaunchWindowingMode( WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY); @@ -170,47 +172,56 @@ public class NotificationRemoteInputManager implements Dumpable { }); } - private void logActionClick( - View view, - NotificationEntry entry, - PendingIntent actionIntent) { + private @Nullable Notification.Action getActionFromView(View view, + NotificationEntry entry, PendingIntent actionIntent) { Integer actionIndex = (Integer) view.getTag(com.android.internal.R.id.notification_action_index_tag); if (actionIndex == null) { - // Custom action button, not logging. - return; + return null; } - ViewParent parent = view.getParent(); if (entry == null) { Log.w(TAG, "Couldn't determine notification for click."); - return; - } - StatusBarNotification statusBarNotification = entry.getSbn(); - String key = statusBarNotification.getKey(); - int buttonIndex = -1; - // If this is a default template, determine the index of the button. - if (view.getId() == com.android.internal.R.id.action0 && - parent != null && parent instanceof ViewGroup) { - ViewGroup actionGroup = (ViewGroup) parent; - buttonIndex = actionGroup.indexOfChild(view); + return null; } - final int count = mEntryManager.getActiveNotificationsCount(); - final int rank = mEntryManager - .getActiveNotificationUnfiltered(key).getRanking().getRank(); // Notification may be updated before this function is executed, and thus play safe // here and verify that the action object is still the one that where the click happens. + StatusBarNotification statusBarNotification = entry.getSbn(); Notification.Action[] actions = statusBarNotification.getNotification().actions; if (actions == null || actionIndex >= actions.length) { Log.w(TAG, "statusBarNotification.getNotification().actions is null or invalid"); - return; + return null ; } final Notification.Action action = statusBarNotification.getNotification().actions[actionIndex]; if (!Objects.equals(action.actionIntent, actionIntent)) { Log.w(TAG, "actionIntent does not match"); + return null; + } + return action; + } + + private void logActionClick( + View view, + NotificationEntry entry, + PendingIntent actionIntent) { + Notification.Action action = getActionFromView(view, entry, actionIntent); + if (action == null) { return; } + ViewParent parent = view.getParent(); + String key = entry.getSbn().getKey(); + int buttonIndex = -1; + // If this is a default template, determine the index of the button. + if (view.getId() == com.android.internal.R.id.action0 && + parent != null && parent instanceof ViewGroup) { + ViewGroup actionGroup = (ViewGroup) parent; + buttonIndex = actionGroup.indexOfChild(view); + } + final int count = mEntryManager.getActiveNotificationsCount(); + final int rank = mEntryManager + .getActiveNotificationUnfiltered(key).getRanking().getRank(); + NotificationVisibility.NotificationLocation location = NotificationLogger.getNotificationLocation( mEntryManager.getActiveNotificationUnfiltered(key)); @@ -813,11 +824,12 @@ public class NotificationRemoteInputManager implements Dumpable { * * @param view * @param pendingIntent + * @param appRequestedAuth * @param defaultHandler * @return true iff the click was handled */ boolean handleRemoteViewClick(View view, PendingIntent pendingIntent, - ClickHandler defaultHandler); + boolean appRequestedAuth, ClickHandler defaultHandler); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index d798692879f5..36f8bcdc9123 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -18,7 +18,6 @@ package com.android.systemui.statusbar; import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN_REVERSE; import static com.android.systemui.statusbar.phone.NotificationIconContainer.IconState.NO_VALUE; -import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT; import android.content.Context; import android.content.res.Configuration; @@ -26,7 +25,6 @@ import android.content.res.Resources; import android.graphics.Rect; import android.os.SystemProperties; import android.util.AttributeSet; -import android.util.Log; import android.util.MathUtils; import android.view.DisplayCutout; import android.view.View; @@ -36,10 +34,8 @@ import android.view.WindowInsets; import android.view.accessibility.AccessibilityNodeInfo; import com.android.internal.annotations.VisibleForTesting; -import com.android.systemui.Dependency; import com.android.systemui.Interpolators; import com.android.systemui.R; -import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; @@ -50,12 +46,8 @@ import com.android.systemui.statusbar.notification.stack.AnimationProperties; import com.android.systemui.statusbar.notification.stack.ExpandableViewState; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.notification.stack.ViewState; -import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.NotificationIconContainer; -import javax.inject.Inject; -import javax.inject.Named; - /** * A notification shelf view that is placed inside the notification scroller. It manages the * overflow icons that don't fit into the regular list anymore. @@ -69,7 +61,6 @@ public class NotificationShelf extends ActivatableNotificationView implements = SystemProperties.getBoolean("debug.icon_scroll_animations", true); private static final int TAG_CONTINUOUS_CLIPPING = R.id.continuous_clipping_tag; private static final String TAG = "NotificationShelf"; - private final KeyguardBypassController mBypassController; private NotificationIconContainer mShelfIcons; private int[] mTmp = new int[2]; @@ -77,7 +68,6 @@ public class NotificationShelf extends ActivatableNotificationView implements private int mIconAppearTopPadding; private float mHiddenShelfIconSize; private int mStatusBarHeight; - private int mStatusBarPaddingStart; private AmbientState mAmbientState; private NotificationStackScrollLayout mHostLayout; private int mMaxLayoutHeight; @@ -88,7 +78,6 @@ public class NotificationShelf extends ActivatableNotificationView implements private int mScrollFastThreshold; private int mIconSize; private int mStatusBarState; - private float mMaxShelfEnd; private int mRelativeOffset; private boolean mInteractive; private float mOpenedAmount; @@ -99,13 +88,10 @@ public class NotificationShelf extends ActivatableNotificationView implements private Rect mClipRect = new Rect(); private int mCutoutHeight; private int mGapHeight; + private NotificationShelfController mController; - @Inject - public NotificationShelf(@Named(VIEW_CONTEXT) Context context, - AttributeSet attrs, - KeyguardBypassController keyguardBypassController) { + public NotificationShelf(Context context, AttributeSet attrs) { super(context, attrs); - mBypassController = keyguardBypassController; } @Override @@ -128,19 +114,6 @@ public class NotificationShelf extends ActivatableNotificationView implements initDimens(); } - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - ((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class)) - .addCallback(this, SysuiStatusBarStateController.RANK_SHELF); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - Dependency.get(StatusBarStateController.class).removeCallback(this); - } - public void bind(AmbientState ambientState, NotificationStackScrollLayout hostLayout) { mAmbientState = ambientState; mHostLayout = hostLayout; @@ -150,7 +123,6 @@ public class NotificationShelf extends ActivatableNotificationView implements Resources res = getResources(); mIconAppearTopPadding = res.getDimensionPixelSize(R.dimen.notification_icon_appear_padding); mStatusBarHeight = res.getDimensionPixelOffset(R.dimen.status_bar_height); - mStatusBarPaddingStart = res.getDimensionPixelOffset(R.dimen.status_bar_padding_start); mPaddingBetweenElements = res.getDimensionPixelSize(R.dimen.notification_divider_height); ViewGroup.LayoutParams layoutParams = getLayoutParams(); @@ -315,9 +287,7 @@ public class NotificationShelf extends ActivatableNotificationView implements transitionAmount = inShelfAmount; } // We don't want to modify the color if the notification is hun'd - boolean canModifyColor = mAmbientState.isShadeExpanded() - && !(mAmbientState.isOnKeyguard() && mBypassController.getBypassEnabled()); - if (isLastChild && canModifyColor) { + if (isLastChild && mController.canModifyColorOfNotifications()) { if (colorOfViewBeforeLast == NO_COLOR) { colorOfViewBeforeLast = ownColorUntinted; } @@ -999,10 +969,6 @@ public class NotificationShelf extends ActivatableNotificationView implements return mInteractive; } - public void setMaxShelfEnd(float maxShelfEnd) { - mMaxShelfEnd = maxShelfEnd; - } - public void setAnimationsEnabled(boolean enabled) { mAnimationsEnabled = enabled; if (!enabled) { @@ -1044,6 +1010,10 @@ public class NotificationShelf extends ActivatableNotificationView implements updateBackgroundColors(); } + public void setController(NotificationShelfController notificationShelfController) { + mController = notificationShelfController; + } + private class ShelfState extends ExpandableViewState { private float openedAmount; private boolean hasItemsInStableShelf; @@ -1056,7 +1026,6 @@ public class NotificationShelf extends ActivatableNotificationView implements } super.applyToView(view); - setMaxShelfEnd(maxShelfEnd); setOpenedAmount(openedAmount); updateAppearance(); setHasItemsInStableShelf(hasItemsInStableShelf); @@ -1070,7 +1039,6 @@ public class NotificationShelf extends ActivatableNotificationView implements } super.animateTo(child, properties); - setMaxShelfEnd(maxShelfEnd); setOpenedAmount(openedAmount); updateAppearance(); setHasItemsInStableShelf(hasItemsInStableShelf); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelfController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelfController.java new file mode 100644 index 000000000000..9f8f8447d72c --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelfController.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2020 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.systemui.statusbar; + +import android.view.View; + +import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController; +import com.android.systemui.statusbar.notification.row.dagger.NotificationRowScope; +import com.android.systemui.statusbar.notification.stack.AmbientState; +import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; +import com.android.systemui.statusbar.phone.KeyguardBypassController; +import com.android.systemui.statusbar.phone.NotificationIconContainer; +import com.android.systemui.statusbar.phone.StatusBarNotificationPresenter; + +import javax.inject.Inject; + +/** + * Controller class for {@link NotificationShelf}. + */ +@NotificationRowScope +public class NotificationShelfController { + private final NotificationShelf mView; + private final ActivatableNotificationViewController mActivatableNotificationViewController; + private final KeyguardBypassController mKeyguardBypassController; + private final SysuiStatusBarStateController mStatusBarStateController; + private final View.OnAttachStateChangeListener mOnAttachStateChangeListener; + private AmbientState mAmbientState; + + @Inject + public NotificationShelfController(NotificationShelf notificationShelf, + ActivatableNotificationViewController activatableNotificationViewController, + KeyguardBypassController keyguardBypassController, + SysuiStatusBarStateController statusBarStateController) { + mView = notificationShelf; + mActivatableNotificationViewController = activatableNotificationViewController; + mKeyguardBypassController = keyguardBypassController; + mStatusBarStateController = statusBarStateController; + mOnAttachStateChangeListener = new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View v) { + mStatusBarStateController.addCallback( + mView, SysuiStatusBarStateController.RANK_SHELF); + } + + @Override + public void onViewDetachedFromWindow(View v) { + mStatusBarStateController.removeCallback(mView); + } + }; + } + + public void init() { + mActivatableNotificationViewController.init(); + mView.setController(this); + mView.addOnAttachStateChangeListener(mOnAttachStateChangeListener); + if (mView.isAttachedToWindow()) { + mOnAttachStateChangeListener.onViewAttachedToWindow(mView); + } + } + + public NotificationShelf getView() { + return mView; + } + + public boolean canModifyColorOfNotifications() { + return mAmbientState.isShadeExpanded() + && !(mAmbientState.isOnKeyguard() && mKeyguardBypassController.getBypassEnabled()); + } + + public NotificationIconContainer getShelfIcons() { + return mView.getShelfIcons(); + } + + public void setCollapsedIcons(NotificationIconContainer notificationIcons) { + mView.setCollapsedIcons(notificationIcons); + } + + public void bind(AmbientState ambientState, + NotificationStackScrollLayout notificationStackScrollLayout) { + mView.bind(ambientState, notificationStackScrollLayout); + mAmbientState = ambientState; + } + + public int getHeight() { + return mView.getHeight(); + } + + public void updateState(AmbientState ambientState) { + mAmbientState = ambientState; + mView.updateState(ambientState); + } + + public int getIntrinsicHeight() { + return mView.getIntrinsicHeight(); + } + + public void setOnActivatedListener(StatusBarNotificationPresenter presenter) { + mView.setOnActivatedListener(presenter); + } + + public void setOnClickListener(View.OnClickListener onClickListener) { + mView.setOnClickListener(onClickListener); + } + + public int getNotGoneIndex() { + return mView.getNotGoneIndex(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java index 7cda23544ca0..27e4adee68ba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java @@ -21,7 +21,7 @@ import android.view.LayoutInflater; import android.view.ViewGroup; import com.android.systemui.R; -import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent; +import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent; import com.android.systemui.statusbar.phone.LockIcon; import com.android.systemui.statusbar.phone.LockscreenLockIconController; import com.android.systemui.statusbar.phone.NotificationPanelView; @@ -41,22 +41,22 @@ public class SuperStatusBarViewFactory { private final Context mContext; private final InjectionInflationController mInjectionInflationController; - private final NotificationRowComponent.Builder mNotificationRowComponentBuilder; private final LockscreenLockIconController mLockIconController; + private final NotificationShelfComponent.Builder mNotificationShelfComponentBuilder; private NotificationShadeWindowView mNotificationShadeWindowView; private StatusBarWindowView mStatusBarWindowView; - private NotificationShelf mNotificationShelf; + private NotificationShelfController mNotificationShelfController; @Inject public SuperStatusBarViewFactory(Context context, InjectionInflationController injectionInflationController, - NotificationRowComponent.Builder notificationRowComponentBuilder, + NotificationShelfComponent.Builder notificationShelfComponentBuilder, LockscreenLockIconController lockIconController) { mContext = context; mInjectionInflationController = injectionInflationController; - mNotificationRowComponentBuilder = notificationRowComponentBuilder; mLockIconController = lockIconController; + mNotificationShelfComponentBuilder = notificationShelfComponentBuilder; } /** @@ -114,25 +114,27 @@ public class SuperStatusBarViewFactory { * isn't immediately attached, but the layout params of this view is used * during inflation. */ - public NotificationShelf getNotificationShelf(ViewGroup container) { - if (mNotificationShelf != null) { - return mNotificationShelf; + public NotificationShelfController getNotificationShelfController(ViewGroup container) { + if (mNotificationShelfController != null) { + return mNotificationShelfController; } - mNotificationShelf = (NotificationShelf) mInjectionInflationController.injectable( - LayoutInflater.from(mContext)).inflate(R.layout.status_bar_notification_shelf, - container, /* attachToRoot= */ false); + NotificationShelf view = (NotificationShelf) LayoutInflater.from(mContext) + .inflate(R.layout.status_bar_notification_shelf, container, /* attachToRoot= */ + false); - NotificationRowComponent component = mNotificationRowComponentBuilder - .activatableNotificationView(mNotificationShelf) - .build(); - component.getActivatableNotificationViewController().init(); - - if (mNotificationShelf == null) { + if (view == null) { throw new IllegalStateException( "R.layout.status_bar_notification_shelf could not be properly inflated"); } - return mNotificationShelf; + + NotificationShelfComponent component = mNotificationShelfComponentBuilder + .notificationShelf(view) + .build(); + mNotificationShelfController = component.getNotificationShelfController(); + mNotificationShelfController.init(); + + return mNotificationShelfController; } public NotificationPanelView getNotificationPanelView() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationShelfComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationShelfComponent.java new file mode 100644 index 000000000000..af8d6ec727d1 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationShelfComponent.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2020 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.systemui.statusbar.notification.row.dagger; + +import com.android.systemui.statusbar.NotificationShelf; +import com.android.systemui.statusbar.NotificationShelfController; +import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; + +import dagger.Binds; +import dagger.BindsInstance; +import dagger.Module; +import dagger.Subcomponent; + +/** + * Dagger subcomponent for NotificationShelf. + */ +@Subcomponent(modules = {ActivatableNotificationViewModule.class, + NotificationShelfComponent.NotificationShelfModule.class}) +@NotificationRowScope +public interface NotificationShelfComponent { + /** + * Builder for {@link NotificationShelfComponent}. + */ + @Subcomponent.Builder + interface Builder { + @BindsInstance + Builder notificationShelf(NotificationShelf view); + NotificationShelfComponent build(); + } + + /** + * Creates a NotificationShelfController. + */ + @NotificationRowScope + NotificationShelfController getNotificationShelfController(); + /** + * Dagger Module that extracts interesting properties from a NotificationShelf. + */ + @Module + abstract class NotificationShelfModule { + + /** NotificationShelf is provided as an instance of ActivatableNotificationView. */ + @Binds + abstract ActivatableNotificationView bindNotificationShelf(NotificationShelf view); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 66a541a923a4..57c1a16a259d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -113,6 +113,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShelf; +import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; @@ -5419,28 +5420,23 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - public void setShelf(NotificationShelf shelf) { + public void setShelfController(NotificationShelfController notificationShelfController) { int index = -1; if (mShelf != null) { index = indexOfChild(mShelf); removeView(mShelf); } - mShelf = shelf; + mShelf = notificationShelfController.getView(); addView(mShelf, index); - mAmbientState.setShelf(shelf); - mStateAnimator.setShelf(shelf); - shelf.bind(mAmbientState, this); + mAmbientState.setShelf(mShelf); + mStateAnimator.setShelf(mShelf); + notificationShelfController.bind(mAmbientState, this); if (ANCHOR_SCROLLING) { mScrollAnchorView = mShelf; } } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - public NotificationShelf getNotificationShelf() { - return mShelf; - } - - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) public void setMaxDisplayedNotifications(int maxDisplayedNotifications) { if (mMaxDisplayedNotifications != maxDisplayedNotifications) { mMaxDisplayedNotifications = maxDisplayedNotifications; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java index 9d3e915cad69..7bbe1c986249 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java @@ -26,7 +26,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.NotificationMediaManager; -import com.android.systemui.statusbar.NotificationShelf; +import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.NotificationUtils; @@ -160,9 +160,9 @@ public class NotificationIconAreaController implements DarkReceiver, } } - public void setupShelf(NotificationShelf shelf) { - mShelfIcons = shelf.getShelfIcons(); - shelf.setCollapsedIcons(mNotificationIcons); + public void setupShelf(NotificationShelfController notificationShelfController) { + mShelfIcons = notificationShelfController.getShelfIcons(); + notificationShelfController.setCollapsedIcons(mNotificationIcons); } public void onDensityOrFontScaleChanged(Context context) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index a87311a69ab5..6946346eee2f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -86,6 +86,7 @@ import com.android.systemui.statusbar.KeyguardAffordanceView; import com.android.systemui.statusbar.KeyguardIndicationController; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationShelf; +import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.StatusBarState; @@ -454,6 +455,7 @@ public class NotificationPanelViewController extends PanelViewController { private boolean mAnimatingQS; private int mOldLayoutDirection; + private NotificationShelfController mNotificationShelfController; private View.AccessibilityDelegate mAccessibilityDelegate = new View.AccessibilityDelegate() { @Override @@ -858,7 +860,7 @@ public class NotificationPanelViewController extends PanelViewController { float minPadding = mClockPositionAlgorithm.getMinStackScrollerPadding(); int notificationPadding = Math.max( 1, mResources.getDimensionPixelSize(R.dimen.notification_divider_height)); - NotificationShelf shelf = mNotificationStackScroller.getNotificationShelf(); + NotificationShelf shelf = mNotificationShelfController.getView(); float shelfSize = shelf.getVisibility() == View.GONE ? 0 @@ -3053,7 +3055,7 @@ public class NotificationPanelViewController extends PanelViewController { } public void initDependencies(StatusBar statusBar, NotificationGroupManager groupManager, - NotificationShelf notificationShelf, + NotificationShelfController notificationShelfController, NotificationIconAreaController notificationIconAreaController, ScrimController scrimController) { setStatusBar(statusBar); @@ -3062,9 +3064,10 @@ public class NotificationPanelViewController extends PanelViewController { mNotificationStackScroller.setIconAreaController(notificationIconAreaController); mNotificationStackScroller.setStatusBar(statusBar); mNotificationStackScroller.setGroupManager(groupManager); - mNotificationStackScroller.setShelf(notificationShelf); + mNotificationStackScroller.setShelfController(notificationShelfController); mNotificationStackScroller.setScrimController(scrimController); updateShowEmptyShadeView(); + mNotificationShelfController = notificationShelfController; } public void showTransientIndication(int id) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index 8cb54eef01b4..e42c3dc4f589 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -284,13 +284,22 @@ public class PhoneStatusBarPolicy mResources.getString(R.string.accessibility_data_saver_on)); mIconController.setIconVisibility(mSlotDataSaver, false); + // privacy items + String microphoneString = mResources.getString(PrivacyType.TYPE_MICROPHONE.getNameId()); + String microphoneDesc = mResources.getString( + R.string.ongoing_privacy_chip_content_multiple_apps, microphoneString); mIconController.setIcon(mSlotMicrophone, PrivacyType.TYPE_MICROPHONE.getIconId(), - mResources.getString(PrivacyType.TYPE_MICROPHONE.getNameId())); + microphoneDesc); mIconController.setIconVisibility(mSlotMicrophone, false); + + String cameraString = mResources.getString(PrivacyType.TYPE_CAMERA.getNameId()); + String cameraDesc = mResources.getString( + R.string.ongoing_privacy_chip_content_multiple_apps, cameraString); mIconController.setIcon(mSlotCamera, PrivacyType.TYPE_CAMERA.getIconId(), - mResources.getString(PrivacyType.TYPE_CAMERA.getNameId())); + cameraDesc); mIconController.setIconVisibility(mSlotCamera, false); + mIconController.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID, mResources.getString(R.string.accessibility_location_active)); mIconController.setIconVisibility(mSlotLocation, false); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index eb626280b494..c8fb4e3372c8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -179,7 +179,6 @@ import com.android.systemui.statusbar.AutoHideUiElement; import com.android.systemui.statusbar.BackDropView; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.CrossFadeHelper; -import com.android.systemui.statusbar.EmptyShadeView; import com.android.systemui.statusbar.GestureRecorder; import com.android.systemui.statusbar.KeyboardShortcuts; import com.android.systemui.statusbar.KeyguardIndicationController; @@ -189,7 +188,7 @@ import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShadeDepthController; -import com.android.systemui.statusbar.NotificationShelf; +import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.NotificationViewHierarchyManager; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.ScrimView; @@ -1029,7 +1028,7 @@ public class StatusBar extends SystemUI implements DemoMode, mStatusBarStateController); mWakeUpCoordinator.setIconAreaController(mNotificationIconAreaController); inflateShelf(); - mNotificationIconAreaController.setupShelf(mNotificationShelf); + mNotificationIconAreaController.setupShelf(mNotificationShelfController); mNotificationPanelViewController.setOnReinflationListener( mNotificationIconAreaController::initAodIcons); mNotificationPanelViewController.addExpansionListener(mWakeUpCoordinator); @@ -1147,7 +1146,8 @@ public class StatusBar extends SystemUI implements DemoMode, }); mScrimController.attachViews(scrimBehind, scrimInFront, scrimForBubble); - mNotificationPanelViewController.initDependencies(this, mGroupManager, mNotificationShelf, + mNotificationPanelViewController.initDependencies(this, mGroupManager, + mNotificationShelfController, mNotificationIconAreaController, mScrimController); BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop); @@ -1310,7 +1310,7 @@ public class StatusBar extends SystemUI implements DemoMode, this /* statusBar */, mShadeController, mCommandQueue, mInitController, mNotificationInterruptStateProvider); - mNotificationShelf.setOnActivatedListener(mPresenter); + mNotificationShelfController.setOnActivatedListener(mPresenter); mRemoteInputManager.getController().addCallback(mNotificationShadeWindowController); mNotificationActivityStarter = @@ -1386,8 +1386,9 @@ public class StatusBar extends SystemUI implements DemoMode, } private void inflateShelf() { - mNotificationShelf = mSuperStatusBarViewFactory.getNotificationShelf(mStackScroller); - mNotificationShelf.setOnClickListener(mGoToLockedShadeListener); + mNotificationShelfController = mSuperStatusBarViewFactory + .getNotificationShelfController(mStackScroller); + mNotificationShelfController.setOnClickListener(mGoToLockedShadeListener); } @Override @@ -4085,8 +4086,7 @@ public class StatusBar extends SystemUI implements DemoMode, private final Optional<Recents> mRecentsOptional; - protected NotificationShelf mNotificationShelf; - protected EmptyShadeView mEmptyShadeView; + protected NotificationShelfController mNotificationShelfController; private final Lazy<AssistManager> mAssistManagerLazy; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java index 72395e68ff07..ac69d9c32c93 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java @@ -244,9 +244,10 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks, @Override public boolean handleRemoteViewClick(View view, PendingIntent pendingIntent, + boolean appRequestedAuth, NotificationRemoteInputManager.ClickHandler defaultHandler) { final boolean isActivity = pendingIntent.isActivity(); - if (isActivity) { + if (isActivity || appRequestedAuth) { mActionClickLogger.logWaitingToCloseKeyguard(pendingIntent); final boolean afterKeyguardGone = mActivityIntentHelper.wouldLaunchResolverActivity( pendingIntent.getIntent(), mLockscreenUserManager.getCurrentUserId()); diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java index 551b7b41212a..d16bedcad960 100644 --- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java +++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java @@ -23,6 +23,7 @@ import android.view.InflateException; import android.view.LayoutInflater; import android.view.View; +import com.android.keyguard.KeyguardClockSwitch; import com.android.keyguard.KeyguardMessageArea; import com.android.keyguard.KeyguardSliceView; import com.android.systemui.dagger.SystemUIRootComponent; @@ -126,11 +127,6 @@ public class InjectionInflationController { NotificationStackScrollLayout createNotificationStackScrollLayout(); /** - * Creates the Shelf. - */ - NotificationShelf creatNotificationShelf(); - - /** * Creates the KeyguardSliceView. */ KeyguardSliceView createKeyguardSliceView(); diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 3455ff47de8d..4b119dd7e176 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -150,6 +150,8 @@ public class VolumeDialogImpl implements VolumeDialog, private boolean mShowing; private boolean mShowA11yStream; + private final boolean mShowLowMediaVolumeIcon; + private int mActiveStream; private int mPrevActiveStream; private boolean mAutomute = VolumePrefs.DEFAULT_ENABLE_AUTOMUTE; @@ -166,7 +168,7 @@ public class VolumeDialogImpl implements VolumeDialog, public VolumeDialogImpl(Context context) { mContext = - new ContextThemeWrapper(context, R.style.qs_theme); + new ContextThemeWrapper(context, R.style.volume_dialog_theme); mController = Dependency.get(VolumeDialogController.class); mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); @@ -175,6 +177,8 @@ public class VolumeDialogImpl implements VolumeDialog, mShowActiveStreamOnly = showActiveStreamOnly(); mHasSeenODICaptionsTooltip = Prefs.getBoolean(context, Prefs.Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP, false); + mShowLowMediaVolumeIcon = + mContext.getResources().getBoolean(R.bool.config_showLowMediaVolumeIcon); } @Override @@ -421,6 +425,7 @@ public class VolumeDialogImpl implements VolumeDialog, row.dndIcon = row.view.findViewById(R.id.dnd_icon); row.slider = row.view.findViewById(R.id.volume_row_slider); row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row)); + row.number = row.view.findViewById(R.id.volume_number); row.anim = null; @@ -1024,19 +1029,28 @@ public class VolumeDialogImpl implements VolumeDialog, final boolean iconEnabled = (mAutomute || ss.muteSupported) && !zenMuted; row.icon.setEnabled(iconEnabled); row.icon.setAlpha(iconEnabled ? 1 : 0.5f); - final int iconRes = - isRingVibrate ? R.drawable.ic_volume_ringer_vibrate - : isRingSilent || zenMuted ? row.iconMuteRes - : ss.routedToBluetooth - ? isStreamMuted(ss) ? R.drawable.ic_volume_media_bt_mute - : R.drawable.ic_volume_media_bt - : isStreamMuted(ss) ? row.iconMuteRes : row.iconRes; + final int iconRes; + if (isRingVibrate) { + iconRes = R.drawable.ic_volume_ringer_vibrate; + } else if (isRingSilent || zenMuted) { + iconRes = row.iconMuteRes; + } else if (ss.routedToBluetooth) { + iconRes = isStreamMuted(ss) ? R.drawable.ic_volume_media_bt_mute + : R.drawable.ic_volume_media_bt; + } else if (isStreamMuted(ss)) { + iconRes = row.iconMuteRes; + } else { + iconRes = mShowLowMediaVolumeIcon && ss.level * 2 < (ss.levelMax + ss.levelMin) + ? R.drawable.ic_volume_media_low : row.iconRes; + } + row.icon.setImageResource(iconRes); row.iconState = iconRes == R.drawable.ic_volume_ringer_vibrate ? Events.ICON_STATE_VIBRATE : (iconRes == R.drawable.ic_volume_media_bt_mute || iconRes == row.iconMuteRes) ? Events.ICON_STATE_MUTE - : (iconRes == R.drawable.ic_volume_media_bt || iconRes == row.iconRes) + : (iconRes == R.drawable.ic_volume_media_bt || iconRes == row.iconRes + || iconRes == R.drawable.ic_volume_media_low) ? Events.ICON_STATE_UNMUTE : Events.ICON_STATE_UNKNOWN; if (iconEnabled) { @@ -1090,6 +1104,7 @@ public class VolumeDialogImpl implements VolumeDialog, final int vlevel = row.ss.muted && (!isRingStream && !zenMuted) ? 0 : row.ss.level; updateVolumeRowSliderH(row, enableSlider, vlevel); + if (row.number != null) row.number.setText(Integer.toString(vlevel)); } private boolean isStreamMuted(final StreamState streamState) { @@ -1115,6 +1130,10 @@ public class VolumeDialogImpl implements VolumeDialog, row.icon.setImageTintList(tint); row.icon.setImageAlpha(alpha); row.cachedTint = tint; + if (row.number != null) { + row.number.setTextColor(tint); + row.number.setAlpha(alpha); + } } private void updateVolumeRowSliderH(VolumeRow row, boolean enable, int vlevel) { @@ -1346,7 +1365,7 @@ public class VolumeDialogImpl implements VolumeDialog, private final class CustomDialog extends Dialog implements DialogInterface { public CustomDialog(Context context) { - super(context, R.style.qs_theme); + super(context, R.style.volume_dialog_theme); } @Override @@ -1458,6 +1477,7 @@ public class VolumeDialogImpl implements VolumeDialog, private TextView header; private ImageButton icon; private SeekBar slider; + private TextView number; private int stream; private StreamState ss; private long userAttempt; // last user-driven slider change diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java index fbc8e9d8de79..ac567e0ae67d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java @@ -25,6 +25,7 @@ import android.content.Context; import android.os.RemoteException; import android.provider.Settings; import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; import android.view.Display; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.IWindowMagnificationConnection; @@ -47,6 +48,7 @@ import org.mockito.MockitoAnnotations; */ @SmallTest @RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper public class IWindowMagnificationConnectionTest extends SysuiTestCase { private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY; @@ -57,7 +59,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { @Mock private IWindowMagnificationConnectionCallback mConnectionCallback; @Mock - private WindowMagnificationController mWindowMagnificationController; + private WindowMagnificationAnimationController mWindowMagnificationAnimationController; @Mock private ModeSwitchesController mModeSwitchesController; private IWindowMagnificationConnection mIWindowMagnificationConnection; @@ -74,7 +76,8 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { any(IWindowMagnificationConnection.class)); mWindowMagnification = new WindowMagnification(getContext(), getContext().getMainThreadHandler(), mCommandQueue, mModeSwitchesController); - mWindowMagnification.mWindowMagnificationController = mWindowMagnificationController; + mWindowMagnification.mWindowMagnificationAnimationController = + mWindowMagnificationAnimationController; mWindowMagnification.requestWindowMagnificationConnection(true); assertNotNull(mIWindowMagnificationConnection); mIWindowMagnificationConnection.setConnectionCallback(mConnectionCallback); @@ -86,7 +89,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { Float.NaN); waitForIdleSync(); - verify(mWindowMagnificationController).enableWindowMagnification(3.0f, Float.NaN, + verify(mWindowMagnificationAnimationController).enableWindowMagnification(3.0f, Float.NaN, Float.NaN); } @@ -99,7 +102,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { mIWindowMagnificationConnection.disableWindowMagnification(TEST_DISPLAY); waitForIdleSync(); - verify(mWindowMagnificationController).deleteWindowMagnification(); + verify(mWindowMagnificationAnimationController).deleteWindowMagnification(); } @Test @@ -107,7 +110,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { mIWindowMagnificationConnection.setScale(TEST_DISPLAY, 3.0f); waitForIdleSync(); - verify(mWindowMagnificationController).setScale(3.0f); + verify(mWindowMagnificationAnimationController).setScale(3.0f); } @Test @@ -115,7 +118,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { mIWindowMagnificationConnection.moveWindowMagnifier(TEST_DISPLAY, 100f, 200f); waitForIdleSync(); - verify(mWindowMagnificationController).moveWindowMagnifier(100f, 200f); + verify(mWindowMagnificationAnimationController).moveWindowMagnifier(100f, 200f); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java new file mode 100644 index 000000000000..b7c198e53cfa --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java @@ -0,0 +1,363 @@ +/* + * Copyright (C) 2020 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.systemui.accessibility; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyFloat; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import android.animation.ValueAnimator; +import android.app.Instrumentation; +import android.content.Context; +import android.os.Handler; +import android.os.SystemClock; +import android.testing.AndroidTestingRunner; +import android.view.SurfaceControl; +import android.view.animation.AccelerateInterpolator; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.MediumTest; + +import com.android.internal.graphics.SfVsyncFrameCallbackProvider; +import com.android.systemui.SysuiTestCase; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import java.util.concurrent.atomic.AtomicReference; + + +@MediumTest +@RunWith(AndroidTestingRunner.class) +public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { + + private static final float DEFAULT_SCALE = 3.0f; + private static final float DEFAULT_CENTER_X = 400.0f; + private static final float DEFAULT_CENTER_Y = 500.0f; + // The duration couldn't too short, otherwise the ValueAnimator won't work in expectation. + private static final long ANIMATION_DURATION_MS = 200; + + private AtomicReference<Float> mCurrentScale = new AtomicReference<>((float) 0); + private AtomicReference<Float> mCurrentCenterX = new AtomicReference<>((float) 0); + private AtomicReference<Float> mCurrentCenterY = new AtomicReference<>((float) 0); + private ArgumentCaptor<Float> mScaleCaptor = ArgumentCaptor.forClass(Float.class); + private ArgumentCaptor<Float> mCenterXCaptor = ArgumentCaptor.forClass(Float.class); + private ArgumentCaptor<Float> mCenterYCaptor = ArgumentCaptor.forClass(Float.class); + + @Mock + Handler mHandler; + @Mock + SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; + @Mock + WindowMagnifierCallback mWindowMagnifierCallback; + + private SpyWindowMagnificationController mController; + private WindowMagnificationController mSpyController; + private WindowMagnificationAnimationController mWindowMagnificationAnimationController; + private Instrumentation mInstrumentation; + private long mWaitingAnimationPeriod; + private long mWaitIntermediateAnimationPeriod; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mInstrumentation = InstrumentationRegistry.getInstrumentation(); + mWaitingAnimationPeriod = ANIMATION_DURATION_MS + 50; + mWaitIntermediateAnimationPeriod = ANIMATION_DURATION_MS / 2; + mController = new SpyWindowMagnificationController(mContext, mHandler, + mSfVsyncFrameProvider, null, new SurfaceControl.Transaction(), + mWindowMagnifierCallback); + mSpyController = mController.getSpyController(); + mWindowMagnificationAnimationController = new WindowMagnificationAnimationController( + mContext, mController, newValueAnimator()); + } + + @Test + public void enableWindowMagnification_disabled_expectedStartAndEndValues() { + enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod); + + verify(mSpyController, atLeast(2)).enableWindowMagnification( + mScaleCaptor.capture(), + mCenterXCaptor.capture(), mCenterYCaptor.capture()); + verifyStartValue(mScaleCaptor, 1.0f); + verifyStartValue(mCenterXCaptor, DEFAULT_CENTER_X); + verifyStartValue(mCenterYCaptor, DEFAULT_CENTER_Y); + verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X, DEFAULT_CENTER_Y); + } + + @Test + public void enableWindowMagnification_enabling_expectedStartAndEndValues() { + enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod); + final float targetScale = DEFAULT_SCALE + 1.0f; + final float targetCenterX = DEFAULT_CENTER_X + 100; + final float targetCenterY = DEFAULT_CENTER_Y + 100; + + mInstrumentation.runOnMainSync(() -> { + Mockito.reset(mSpyController); + mWindowMagnificationAnimationController.enableWindowMagnification(targetScale, + targetCenterX, targetCenterY); + mCurrentScale.set(mController.getScale()); + mCurrentCenterX.set(mController.getCenterX()); + mCurrentCenterY.set(mController.getCenterY()); + }); + + SystemClock.sleep(mWaitingAnimationPeriod); + + verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(), + mCenterXCaptor.capture(), mCenterYCaptor.capture()); + verifyStartValue(mScaleCaptor, mCurrentScale.get()); + verifyStartValue(mCenterXCaptor, mCurrentCenterX.get()); + verifyStartValue(mCenterYCaptor, mCurrentCenterY.get()); + verifyFinalSpec(targetScale, targetCenterX, targetCenterY); + } + + @Test + public void enableWindowMagnification_disabling_expectedStartAndEndValues() { + enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod); + deleteWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod); + final float targetScale = DEFAULT_SCALE + 1.0f; + final float targetCenterX = DEFAULT_CENTER_X + 100; + final float targetCenterY = DEFAULT_CENTER_Y + 100; + + mInstrumentation.runOnMainSync( + () -> { + Mockito.reset(mSpyController); + mWindowMagnificationAnimationController.enableWindowMagnification(targetScale, + targetCenterX, targetCenterY); + mCurrentScale.set(mController.getScale()); + mCurrentCenterX.set(mController.getCenterX()); + mCurrentCenterY.set(mController.getCenterY()); + }); + SystemClock.sleep(mWaitingAnimationPeriod); + + verify(mSpyController, atLeast(2)).enableWindowMagnification( + mScaleCaptor.capture(), + mCenterXCaptor.capture(), mCenterYCaptor.capture()); + //Animating in reverse, so we only check if the start values are greater than current. + assertTrue(mScaleCaptor.getAllValues().get(0) > mCurrentScale.get()); + assertEquals(targetScale, mScaleCaptor.getValue(), 0f); + assertTrue(mCenterXCaptor.getAllValues().get(0) > mCurrentCenterX.get()); + assertEquals(targetCenterX, mCenterXCaptor.getValue(), 0f); + assertTrue(mCenterYCaptor.getAllValues().get(0) > mCurrentCenterY.get()); + assertEquals(targetCenterY, mCenterYCaptor.getValue(), 0f); + verifyFinalSpec(targetScale, targetCenterX, targetCenterY); + } + + @Test + public void enableWindowMagnificationWithSameScale_doNothing() { + enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod); + + enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod); + + verify(mSpyController, never()).enableWindowMagnification(anyFloat(), anyFloat(), + anyFloat()); + } + + @Test + public void setScale_enabled_expectedScale() { + enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod); + + mInstrumentation.runOnMainSync( + () -> mWindowMagnificationAnimationController.setScale(DEFAULT_SCALE + 1)); + + verify(mSpyController).setScale(DEFAULT_SCALE + 1); + verifyFinalSpec(DEFAULT_SCALE + 1, DEFAULT_CENTER_X, DEFAULT_CENTER_Y); + } + + @Test + public void deleteWindowMagnification_enabled_expectedStartAndEndValues() { + enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod); + + deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod); + + verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(), + mCenterXCaptor.capture(), mCenterYCaptor.capture()); + verify(mSpyController).deleteWindowMagnification(); + verifyStartValue(mScaleCaptor, DEFAULT_SCALE); + verifyStartValue(mCenterXCaptor, Float.NaN); + verifyStartValue(mCenterYCaptor, Float.NaN); + verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN); + } + + @Test + public void deleteWindowMagnification_disabled_doNothing() { + deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod); + + Mockito.verifyNoMoreInteractions(mSpyController); + } + + @Test + public void deleteWindowMagnification_enabling_checkStartAndEndValues() { + enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod); + + //It just reverse the animation, so we don't need to wait the whole duration. + mInstrumentation.runOnMainSync( + () -> { + Mockito.reset(mSpyController); + mWindowMagnificationAnimationController.deleteWindowMagnification(); + mCurrentScale.set(mController.getScale()); + mCurrentCenterX.set(mController.getCenterX()); + mCurrentCenterY.set(mController.getCenterY()); + }); + SystemClock.sleep(mWaitingAnimationPeriod); + + verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(), + mCenterXCaptor.capture(), mCenterYCaptor.capture()); + verify(mSpyController).deleteWindowMagnification(); + + //The animation is in verse, so we only check the start values should no be greater than + // the current one. + assertTrue(mScaleCaptor.getAllValues().get(0) <= mCurrentScale.get()); + assertEquals(1.0f, mScaleCaptor.getValue(), 0f); + verifyStartValue(mCenterXCaptor, Float.NaN); + verifyStartValue(mCenterYCaptor, Float.NaN); + verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN); + } + + @Test + public void deleteWindowMagnification_disabling_checkStartAndValues() { + enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod); + deleteWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod); + + deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod); + + verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(), + mCenterXCaptor.capture(), mCenterYCaptor.capture()); + verify(mSpyController).deleteWindowMagnification(); + assertEquals(1.0f, mScaleCaptor.getValue(), 0f); + verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN); + } + + @Test + public void moveWindowMagnifier_enabled() { + enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod); + + mInstrumentation.runOnMainSync( + () -> mWindowMagnificationAnimationController.moveWindowMagnifier(100f, 200f)); + + verify(mSpyController).moveWindowMagnifier(100f, 200f); + verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X + 100f, DEFAULT_CENTER_Y + 100f); + } + + @Test + public void onConfigurationChanged_passThrough() { + mWindowMagnificationAnimationController.onConfigurationChanged(100); + + verify(mSpyController).onConfigurationChanged(100); + } + private void verifyFinalSpec(float expectedScale, float expectedCenterX, + float expectedCenterY) { + assertEquals(expectedScale, mController.getScale(), 0f); + assertEquals(expectedCenterX, mController.getCenterX(), 0f); + assertEquals(expectedCenterY, mController.getCenterY(), 0f); + } + + private void enableWindowMagnificationAndWaitAnimating(long duration) { + mInstrumentation.runOnMainSync( + () -> { + Mockito.reset(mSpyController); + mWindowMagnificationAnimationController.enableWindowMagnification(DEFAULT_SCALE, + DEFAULT_CENTER_X, DEFAULT_CENTER_Y); + }); + SystemClock.sleep(duration); + } + + private void deleteWindowMagnificationAndWaitAnimating(long duration) { + mInstrumentation.runOnMainSync( + () -> { + resetMockObjects(); + mWindowMagnificationAnimationController.deleteWindowMagnification(); + }); + SystemClock.sleep(duration); + } + + private void verifyStartValue(ArgumentCaptor<Float> captor, float startValue) { + assertEquals(startValue, captor.getAllValues().get(0), 0f); + } + + private void resetMockObjects() { + Mockito.reset(mSpyController); + } + + /** + * It observes the methods in {@link WindowMagnificationController} since we couldn't spy it + * directly. + */ + private static class SpyWindowMagnificationController extends WindowMagnificationController { + private WindowMagnificationController mSpyController; + + SpyWindowMagnificationController(Context context, Handler handler, + SfVsyncFrameCallbackProvider sfVsyncFrameProvider, + MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction, + WindowMagnifierCallback callback) { + super(context, handler, sfVsyncFrameProvider, mirrorWindowControl, transaction, + callback); + mSpyController = Mockito.mock(WindowMagnificationController.class); + } + + WindowMagnificationController getSpyController() { + return mSpyController; + } + + @Override + void enableWindowMagnification(float scale, float centerX, float centerY) { + super.enableWindowMagnification(scale, centerX, centerY); + mSpyController.enableWindowMagnification(scale, centerX, centerY); + } + + @Override + void deleteWindowMagnification() { + super.deleteWindowMagnification(); + mSpyController.deleteWindowMagnification(); + } + + @Override + void moveWindowMagnifier(float offsetX, float offsetY) { + super.moveWindowMagnifier(offsetX, offsetX); + mSpyController.moveWindowMagnifier(offsetX, offsetY); + } + + @Override + void setScale(float scale) { + super.setScale(scale); + mSpyController.setScale(scale); + } + + @Override + void onConfigurationChanged(int configDiff) { + super.onConfigurationChanged(configDiff); + mSpyController.onConfigurationChanged(configDiff); + } + + } + + private static ValueAnimator newValueAnimator() { + final ValueAnimator valueAnimator = new ValueAnimator(); + valueAnimator.setDuration(ANIMATION_DURATION_MS); + valueAnimator.setInterpolator(new AccelerateInterpolator(2.5f)); + valueAnimator.setFloatValues(0.0f, 1.0f); + return valueAnimator; + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java index 2007fbb8fc6c..f1f394e70689 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -18,6 +18,7 @@ package com.android.systemui.accessibility; import static android.view.Choreographer.FrameCallback; +import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.atLeastOnce; @@ -26,8 +27,12 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.Instrumentation; +import android.content.Context; +import android.content.pm.ActivityInfo; import android.os.Handler; import android.testing.AndroidTestingRunner; +import android.view.Display; +import android.view.Surface; import android.view.SurfaceControl; import androidx.test.InstrumentationRegistry; @@ -41,6 +46,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; @SmallTest @@ -57,12 +63,14 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { WindowMagnifierCallback mWindowMagnifierCallback; @Mock SurfaceControl.Transaction mTransaction; + private Context mContext; private WindowMagnificationController mWindowMagnificationController; private Instrumentation mInstrumentation; @Before public void setUp() { MockitoAnnotations.initMocks(this); + mContext = Mockito.spy(getContext()); mInstrumentation = InstrumentationRegistry.getInstrumentation(); doAnswer(invocation -> { FrameCallback callback = invocation.getArgument(0); @@ -73,8 +81,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { when(mTransaction.remove(any())).thenReturn(mTransaction); when(mTransaction.setGeometry(any(), any(), any(), anyInt())).thenReturn(mTransaction); - - mWindowMagnificationController = new WindowMagnificationController(getContext(), + mWindowMagnificationController = new WindowMagnificationController(mContext, mHandler, mSfVsyncFrameProvider, mMirrorWindowControl, mTransaction, mWindowMagnifierCallback); verify(mMirrorWindowControl).setWindowDelegate( @@ -83,9 +90,8 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @After public void tearDown() { - mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.deleteWindowMagnification(); - }); + mInstrumentation.runOnMainSync( + () -> mWindowMagnificationController.deleteWindowMagnification()); } @Test @@ -121,4 +127,27 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { verify(mSfVsyncFrameProvider, atLeastOnce()).postFrameCallback(any()); } + + @Test + public void setScale_enabled_expectedValue() { + mInstrumentation.runOnMainSync( + () -> mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN, + Float.NaN)); + + mInstrumentation.runOnMainSync(() -> mWindowMagnificationController.setScale(3.0f)); + + assertEquals(3.0f, mWindowMagnificationController.getScale(), 0); + } + + @Test + public void onConfigurationChanged_disabled_withoutException() { + Display display = Mockito.spy(mContext.getDisplay()); + when(display.getRotation()).thenReturn(Surface.ROTATION_90); + when(mContext.getDisplay()).thenReturn(display); + + mInstrumentation.runOnMainSync(() -> { + mWindowMagnificationController.onConfigurationChanged(ActivityInfo.CONFIG_DENSITY); + mWindowMagnificationController.onConfigurationChanged(ActivityInfo.CONFIG_ORIENTATION); + }); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java index 41360130ac65..936558bca2d2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java @@ -26,6 +26,7 @@ import android.content.res.Configuration; import android.graphics.Rect; import android.os.RemoteException; import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; import android.view.Display; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.IWindowMagnificationConnection; @@ -45,6 +46,7 @@ import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper public class WindowMagnificationTest extends SysuiTestCase { @Mock diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java index b7589534a770..1538a32ecf8a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -60,6 +60,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.colorextraction.ColorExtractor; import com.android.internal.statusbar.IStatusBarService; +import com.android.systemui.SystemUIFactory; import com.android.systemui.SysuiTestCase; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dump.DumpManager; @@ -70,7 +71,9 @@ import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationRemoveInterceptor; +import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.RankingBuilder; +import com.android.systemui.statusbar.SuperStatusBarViewFactory; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; @@ -79,8 +82,10 @@ import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationTestHelper; +import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBypassController; +import com.android.systemui.statusbar.phone.LockscreenLockIconController; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; @@ -90,6 +95,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.util.FloatingContentCoordinator; +import com.android.systemui.util.InjectionInflationController; import com.google.common.collect.ImmutableList; @@ -174,6 +180,8 @@ public class BubbleControllerTest extends SysuiTestCase { @Mock private ShadeController mShadeController; @Mock + private NotificationShelfComponent mNotificationShelfComponent; + @Mock private NotifPipeline mNotifPipeline; @Mock private FeatureFlags mFeatureFlagsOldPipeline; @@ -185,11 +193,14 @@ public class BubbleControllerTest extends SysuiTestCase { private IStatusBarService mStatusBarService; @Mock private LauncherApps mLauncherApps; + @Mock private LockscreenLockIconController mLockIconController; private BubbleData mBubbleData; private TestableLooper mTestableLooper; + private SuperStatusBarViewFactory mSuperStatusBarViewFactory; + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -199,6 +210,23 @@ public class BubbleControllerTest extends SysuiTestCase { mContext.addMockSystemService(FaceManager.class, mFaceManager); when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors); + mSuperStatusBarViewFactory = new SuperStatusBarViewFactory(mContext, + new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()), + new NotificationShelfComponent.Builder() { + @Override + public NotificationShelfComponent.Builder notificationShelf( + NotificationShelf view) { + return this; + } + + @Override + public NotificationShelfComponent build() { + return mNotificationShelfComponent; + } + }, + mLockIconController); + + // Bubbles get added to status bar window view mNotificationShadeWindowController = new NotificationShadeWindowController(mContext, mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController, mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java index 43bf19111049..0e7cb79ec266 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java @@ -58,6 +58,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.colorextraction.ColorExtractor; import com.android.internal.statusbar.IStatusBarService; +import com.android.systemui.SystemUIFactory; import com.android.systemui.SysuiTestCase; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dump.DumpManager; @@ -66,7 +67,9 @@ import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; +import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.RankingBuilder; +import com.android.systemui.statusbar.SuperStatusBarViewFactory; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationFilter; @@ -75,7 +78,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationTestHelper; -import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent; +import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.LockscreenLockIconController; @@ -88,6 +91,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.util.FloatingContentCoordinator; +import com.android.systemui.util.InjectionInflationController; import org.junit.Before; import org.junit.Ignore; @@ -168,7 +172,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { @Mock private ShadeController mShadeController; @Mock - private NotificationRowComponent mNotificationRowComponent; + private NotificationShelfComponent mNotificationShelfComponent; @Mock private NotifPipeline mNotifPipeline; @Mock @@ -185,6 +189,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { private BubbleData mBubbleData; private TestableLooper mTestableLooper; + private SuperStatusBarViewFactory mSuperStatusBarViewFactory; @Before public void setUp() throws Exception { @@ -195,6 +200,22 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { mContext.addMockSystemService(FaceManager.class, mFaceManager); when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors); + mSuperStatusBarViewFactory = new SuperStatusBarViewFactory(mContext, + new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()), + new NotificationShelfComponent.Builder() { + @Override + public NotificationShelfComponent.Builder notificationShelf( + NotificationShelf view) { + return this; + } + + @Override + public NotificationShelfComponent build() { + return mNotificationShelfComponent; + } + }, + mLockIconController); + // Bubbles get added to status bar window view mNotificationShadeWindowController = new NotificationShadeWindowController(mContext, mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt index 3789e6ef1f65..a4ebe1ff2a4e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt @@ -13,6 +13,7 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dump.DumpManager +import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.SbnBuilder import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.eq @@ -58,6 +59,7 @@ class MediaDataManagerTest : SysuiTestCase() { @Mock lateinit var mediaTimeoutListener: MediaTimeoutListener @Mock lateinit var mediaResumeListener: MediaResumeListener @Mock lateinit var pendingIntent: PendingIntent + @Mock lateinit var activityStarter: ActivityStarter @JvmField @Rule val mockito = MockitoJUnit.rule() lateinit var mediaDataManager: MediaDataManager lateinit var mediaNotification: StatusBarNotification @@ -68,8 +70,8 @@ class MediaDataManagerTest : SysuiTestCase() { backgroundExecutor = FakeExecutor(FakeSystemClock()) mediaDataManager = MediaDataManager(context, backgroundExecutor, foregroundExecutor, mediaControllerFactory, broadcastDispatcher, dumpManager, - mediaTimeoutListener, mediaResumeListener, useMediaResumption = true, - useQsMediaPlayer = true) + mediaTimeoutListener, mediaResumeListener, activityStarter, + useMediaResumption = true, useQsMediaPlayer = true) session = MediaSession(context, "MediaDataManagerTestSession") mediaNotification = SbnBuilder().run { setPkg(PACKAGE_NAME) diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java index bdb7166f5db1..c8e1a74d969f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java @@ -78,7 +78,7 @@ import javax.inject.Provider; @RunWith(AndroidTestingRunner.class) @SmallTest -@RunWithLooper +@RunWithLooper(setAsMainLooper = true) public class QSTileHostTest extends SysuiTestCase { private static String MOCK_STATE_STRING = "MockState"; diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt index c2579dd46e78..3aa40dec1fad 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt @@ -53,7 +53,7 @@ import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidTestingRunner::class) -@TestableLooper.RunWithLooper +@TestableLooper.RunWithLooper(setAsMainLooper = true) class CustomTileTest : SysuiTestCase() { companion object { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java index cccb65d11228..61a0d6c17eed 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java @@ -244,6 +244,8 @@ public class QSTileImplTest extends SysuiTestCase { assertNotEquals(DESTROYED, mTile.getLifecycle().getCurrentState()); mTile.handleDestroy(); + mTestableLooper.processAllMessages(); + assertEquals(DESTROYED, mTile.getLifecycle().getCurrentState()); } @@ -298,6 +300,25 @@ public class QSTileImplTest extends SysuiTestCase { assertNotEquals(DESTROYED, mTile.getLifecycle().getCurrentState()); } + @Test + public void testRefreshStateAfterDestroyedDoesNotCrash() { + mTile.destroy(); + mTile.refreshState(); + + mTestableLooper.processAllMessages(); + } + + @Test + public void testSetListeningAfterDestroyedDoesNotCrash() { + Object o = new Object(); + mTile.destroy(); + + mTile.setListening(o, true); + mTile.setListening(o, false); + + mTestableLooper.processAllMessages(); + } + private void assertEvent(UiEventLogger.UiEventEnum eventType, UiEventLoggerFake.FakeUiEvent fakeEvent) { assertEquals(eventType.getId(), fakeEvent.eventId); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt index f70106a64968..2006a75c0e16 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt @@ -38,7 +38,7 @@ import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @RunWith(AndroidTestingRunner::class) -@RunWithLooper +@RunWithLooper(setAsMainLooper = true) @SmallTest class BatterySaverTileTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java index 8ece62281f77..5d14898cdd2c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java @@ -58,7 +58,7 @@ import java.util.List; @RunWith(AndroidTestingRunner.class) -@TestableLooper.RunWithLooper +@TestableLooper.RunWithLooper(setAsMainLooper = true) @SmallTest public class CastTileTest extends SysuiTestCase { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index ddac2ecbd6eb..85701c24f7d6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -64,6 +64,7 @@ import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShelf; +import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; @@ -197,7 +198,10 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mEntryManager.setUpWithPresenter(mock(NotificationPresenter.class)); when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false); + NotificationShelfController notificationShelfController = + mock(NotificationShelfController.class); NotificationShelf notificationShelf = mock(NotificationShelf.class); + when(notificationShelfController.getView()).thenReturn(notificationShelf); when(mNotificationSectionsManager.createSectionsForBuckets()).thenReturn( new NotificationSection[]{ mNotificationSection @@ -230,7 +234,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { verify(mLockscreenUserManager).addUserChangedListener(userChangedCaptor.capture()); mUserChangedListener = userChangedCaptor.getValue(); mStackScroller = spy(mStackScrollerInternal); - mStackScroller.setShelf(notificationShelf); + mStackScroller.setShelfController(notificationShelfController); mStackScroller.setStatusBar(mBar); mStackScroller.setScrimController(mock(ScrimController.class)); mStackScroller.setGroupManager(mGroupManager); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java index c7434f6fd95f..bf4ccd22effd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java @@ -63,7 +63,7 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.FlingAnimationUtils; import com.android.systemui.statusbar.KeyguardAffordanceView; import com.android.systemui.statusbar.NotificationLockscreenUserManager; -import com.android.systemui.statusbar.NotificationShelf; +import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.StatusBarStateControllerImpl; import com.android.systemui.statusbar.SysuiStatusBarStateController; @@ -115,7 +115,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { @Mock private HeadsUpManagerPhone mHeadsUpManager; @Mock - private NotificationShelf mNotificationShelf; + private NotificationShelfController mNotificationShelfController; @Mock private NotificationGroupManager mGroupManager; @Mock @@ -246,7 +246,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { mBiometricUnlockController, mStatusBarKeyguardViewManager, () -> mKeyguardClockSwitchController); mNotificationPanelViewController.initDependencies(mStatusBar, mGroupManager, - mNotificationShelf, mNotificationAreaController, mScrimController); + mNotificationShelfController, mNotificationAreaController, mScrimController); mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager); mNotificationPanelViewController.setBar(mPanelBar); diff --git a/services/Android.bp b/services/Android.bp index ef52c2aff002..b348b91a1bd7 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -156,14 +156,10 @@ droidstubs { java_library { name: "android_system_server_stubs_current", - defaults: ["android_stubs_dists_default"], srcs: [":services-stubs.sources"], installable: false, static_libs: ["android_module_lib_stubs_current"], sdk_version: "none", system_modules: "none", java_version: "1.8", - dist: { - dir: "apistubs/android/system-server", - }, } diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java index bd25f2bea881..3ee5b28ee338 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java @@ -25,10 +25,12 @@ import static java.util.Arrays.copyOfRange; import android.annotation.Nullable; import android.content.Context; +import android.graphics.Point; import android.provider.Settings; import android.util.Log; import android.util.MathUtils; import android.util.Slog; +import android.view.Display; import android.view.MotionEvent; import com.android.internal.annotations.VisibleForTesting; @@ -90,6 +92,8 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl private MotionEventDispatcherDelegate mMotionEventDispatcherDelegate; private final int mDisplayId; + private final Context mContext; + private final Point mTempPoint = new Point(); private final Queue<MotionEvent> mDebugOutputEventHistory; @@ -107,7 +111,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl Slog.i(LOG_TAG, "WindowMagnificationGestureHandler() , displayId = " + displayId + ")"); } - + mContext = context; mWindowMagnificationMgr = windowMagnificationMgr; mDetectShortcutTrigger = detectShortcutTrigger; mDisplayId = displayId; @@ -184,7 +188,14 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl if (!mDetectShortcutTrigger) { return; } - toggleMagnification(Float.NaN, Float.NaN); + final Point screenSize = mTempPoint; + getScreenSize(mTempPoint); + toggleMagnification(screenSize.x / 2.0f, screenSize.y / 2.0f); + } + + private void getScreenSize(Point outSize) { + final Display display = mContext.getDisplay(); + display.getRealSize(outSize); } @Override diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java index 1c3116699b2d..a92d334a94fa 100644 --- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java @@ -27,6 +27,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentSender; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.graphics.drawable.Drawable; @@ -214,7 +215,13 @@ final class SaveUi { return componentName; } intent.addFlags(Intent.FLAG_ACTIVITY_MATCH_EXTERNAL); - return intent.resolveActivity(packageManager); + final ActivityInfo ai = + intent.resolveActivityInfo(packageManager, PackageManager.MATCH_INSTANT); + if (ai != null) { + return new ComponentName(ai.applicationInfo.packageName, ai.name); + } + + return null; } }; final LayoutInflater inflater = LayoutInflater.from(context); diff --git a/services/core/Android.bp b/services/core/Android.bp index e76ec743661c..addaa6568665 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -2,38 +2,25 @@ filegroup { name: "services.core-sources", srcs: ["java/**/*.java"], path: "java", - visibility: ["//frameworks/base/services"], -} - -java_library { - name: "protolog-common", - srcs: [ - "java/com/android/server/protolog/common/**/*.java", - ], - host_supported: true, -} - -java_library { - name: "services.core.wm.protologgroups", - srcs: [ - "java/com/android/server/wm/ProtoLogGroup.java", + visibility: [ + "//frameworks/base/services", + "//frameworks/base/core/java/com/android/internal/protolog", ], - static_libs: ["protolog-common"], } genrule { name: "services.core.protologsrc", srcs: [ - ":services.core.wm.protologgroups", + ":protolog-groups", ":services.core-sources", ], tools: ["protologtool"], cmd: "$(location protologtool) transform-protolog-calls " + - "--protolog-class com.android.server.protolog.common.ProtoLog " + - "--protolog-impl-class com.android.server.protolog.ProtoLogImpl " + - "--protolog-cache-class 'com.android.server.protolog.ProtoLog$$Cache' " + - "--loggroups-class com.android.server.wm.ProtoLogGroup " + - "--loggroups-jar $(location :services.core.wm.protologgroups) " + + "--protolog-class com.android.internal.protolog.common.ProtoLog " + + "--protolog-impl-class com.android.internal.protolog.ProtoLogImpl " + + "--protolog-cache-class 'com.android.server.wm.ProtoLogCache' " + + "--loggroups-class com.android.internal.protolog.ProtoLogGroup " + + "--loggroups-jar $(location :protolog-groups) " + "--output-srcjar $(out) " + "$(locations :services.core-sources)", out: ["services.core.protolog.srcjar"], @@ -42,14 +29,14 @@ genrule { genrule { name: "generate-protolog.json", srcs: [ - ":services.core.wm.protologgroups", + ":protolog-groups", ":services.core-sources", ], tools: ["protologtool"], cmd: "$(location protologtool) generate-viewer-config " + - "--protolog-class com.android.server.protolog.common.ProtoLog " + - "--loggroups-class com.android.server.wm.ProtoLogGroup " + - "--loggroups-jar $(location :services.core.wm.protologgroups) " + + "--protolog-class com.android.internal.protolog.common.ProtoLog " + + "--loggroups-class com.android.internal.protolog.ProtoLogGroup " + + "--loggroups-jar $(location :protolog-groups) " + "--viewer-conf $(out) " + "$(locations :services.core-sources)", out: ["services.core.protolog.json"], @@ -109,6 +96,7 @@ java_library_static { ], static_libs: [ + "protolog-lib", "time_zone_distro", "time_zone_distro_installer", "android.hardware.authsecret-V1.0-java", diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java index a3c04be02c6f..c9513592ea79 100644 --- a/services/core/java/com/android/server/BinderCallsStatsService.java +++ b/services/core/java/com/android/server/BinderCallsStatsService.java @@ -28,7 +28,9 @@ import android.database.ContentObserver; import android.net.Uri; import android.os.BatteryStatsInternal; import android.os.Binder; +import android.os.ParcelFileDescriptor; import android.os.Process; +import android.os.ShellCommand; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; @@ -308,50 +310,134 @@ public class BinderCallsStatsService extends Binder { } boolean verbose = false; + int worksourceUid = Process.INVALID_UID; if (args != null) { - for (final String arg : args) { + for (int i = 0; i < args.length; i++) { + String arg = args[i]; if ("-a".equals(arg)) { verbose = true; - } else if ("--reset".equals(arg)) { + } else if ("-h".equals(arg)) { + pw.println("dumpsys binder_calls_stats options:"); + pw.println(" -a: Verbose"); + pw.println(" --work-source-uid <UID>: Dump binder calls from the UID"); + return; + } else if ("--work-source-uid".equals(arg)) { + i++; + if (i >= args.length) { + throw new IllegalArgumentException( + "Argument expected after \"" + arg + "\""); + } + String uidArg = args[i]; + try { + worksourceUid = Integer.parseInt(uidArg); + } catch (NumberFormatException e) { + pw.println("Invalid UID: " + uidArg); + return; + } + } + } + + if (args.length > 0 && worksourceUid == Process.INVALID_UID) { + // For compatibility, support "cmd"-style commands when passed to "dumpsys". + BinderCallsStatsShellCommand command = new BinderCallsStatsShellCommand(pw); + int status = command.exec(this, null, FileDescriptor.out, FileDescriptor.err, args); + if (status == 0) { + return; + } + } + } + mBinderCallsStats.dump(pw, AppIdToPackageMap.getSnapshot(), worksourceUid, verbose); + } + + @Override + public int handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out, + ParcelFileDescriptor err, String[] args) { + ShellCommand command = new BinderCallsStatsShellCommand(null); + int status = command.exec(this, in.getFileDescriptor(), out.getFileDescriptor(), + err.getFileDescriptor(), args); + if (status != 0) { + command.onHelp(); + } + return status; + } + + private class BinderCallsStatsShellCommand extends ShellCommand { + private final PrintWriter mPrintWriter; + + BinderCallsStatsShellCommand(PrintWriter printWriter) { + mPrintWriter = printWriter; + } + + @Override + public PrintWriter getOutPrintWriter() { + if (mPrintWriter != null) { + return mPrintWriter; + } + return super.getOutPrintWriter(); + } + + @Override + public int onCommand(String cmd) { + PrintWriter pw = getOutPrintWriter(); + if (cmd == null) { + return -1; + } + + switch (cmd) { + case "--reset": reset(); pw.println("binder_calls_stats reset."); - return; - } else if ("--enable".equals(arg)) { + break; + case "--enable": Binder.setObserver(mBinderCallsStats); - return; - } else if ("--disable".equals(arg)) { + break; + case "--disable": Binder.setObserver(null); - return; - } else if ("--no-sampling".equals(arg)) { + break; + case "--no-sampling": mBinderCallsStats.setSamplingInterval(1); - return; - } else if ("--enable-detailed-tracking".equals(arg)) { + break; + case "--enable-detailed-tracking": SystemProperties.set(PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, "1"); mBinderCallsStats.setDetailedTracking(true); pw.println("Detailed tracking enabled"); - return; - } else if ("--disable-detailed-tracking".equals(arg)) { + break; + case "--disable-detailed-tracking": SystemProperties.set(PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, ""); mBinderCallsStats.setDetailedTracking(false); pw.println("Detailed tracking disabled"); - return; - } else if ("--dump-worksource-provider".equals(arg)) { + break; + case "--dump-worksource-provider": + mBinderCallsStats.setDetailedTracking(true); mWorkSourceProvider.dump(pw, AppIdToPackageMap.getSnapshot()); - return; - } else if ("-h".equals(arg)) { - pw.println("binder_calls_stats commands:"); - pw.println(" --reset: Reset stats"); - pw.println(" --enable: Enable tracking binder calls"); - pw.println(" --disable: Disables tracking binder calls"); - pw.println(" --no-sampling: Tracks all calls"); - pw.println(" --enable-detailed-tracking: Enables detailed tracking"); - pw.println(" --disable-detailed-tracking: Disables detailed tracking"); - return; - } else { - pw.println("Unknown option: " + arg); - } + break; + case "--work-source-uid": + String uidArg = getNextArgRequired(); + try { + int uid = Integer.parseInt(uidArg); + mBinderCallsStats.recordAllCallsForWorkSourceUid(uid); + } catch (NumberFormatException e) { + pw.println("Invalid UID: " + uidArg); + return -1; + } + break; + default: + return handleDefaultCommands(cmd); } + return 0; + } + + @Override + public void onHelp() { + PrintWriter pw = getOutPrintWriter(); + pw.println("binder_calls_stats commands:"); + pw.println(" --reset: Reset stats"); + pw.println(" --enable: Enable tracking binder calls"); + pw.println(" --disable: Disables tracking binder calls"); + pw.println(" --no-sampling: Tracks all calls"); + pw.println(" --enable-detailed-tracking: Enables detailed tracking"); + pw.println(" --disable-detailed-tracking: Disables detailed tracking"); + pw.println(" --work-source-uid <UID>: Track all binder calls from the UID"); } - mBinderCallsStats.dump(pw, AppIdToPackageMap.getSnapshot(), verbose); } } diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index 59ac09ca2f3d..32d02fb17983 100644 --- a/services/core/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java @@ -114,9 +114,6 @@ public class VibratorService extends IVibratorService.Stub private static final VibrationAttributes DEFAULT_ATTRIBUTES = new VibrationAttributes.Builder().build(); - // If HAL supports callbacks set the timeout to ASYNC_TIMEOUT_MULTIPLIER * duration. - private static final long ASYNC_TIMEOUT_MULTIPLIER = 2; - // A mapping from the intensity adjustment to the scaling to apply, where the intensity // adjustment is defined as the delta between the default intensity level and the user selected // intensity level. It's important that we apply the scaling on the delta between the two so @@ -187,8 +184,8 @@ public class VibratorService extends IVibratorService.Stub static native int[] vibratorGetSupportedEffects(long controllerPtr); - static native long vibratorPerformEffect(long effect, long strength, Vibration vibration, - boolean withCallback); + static native long vibratorPerformEffect( + long controllerPtr, long effect, long strength, Vibration vibration); static native void vibratorPerformComposedEffect(long controllerPtr, VibrationEffect.Composition.PrimitiveEffect[] effect, Vibration vibration); @@ -898,19 +895,11 @@ public class VibratorService extends IVibratorService.Stub } } - private final Runnable mVibrationEndRunnable = new Runnable() { - @Override - public void run() { - onVibrationFinished(); - } - }; - @GuardedBy("mLock") private void doCancelVibrateLocked() { Trace.asyncTraceEnd(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doCancelVibrateLocked"); try { - mH.removeCallbacks(mVibrationEndRunnable); if (mThread != null) { mThread.cancel(); mThread = null; @@ -958,13 +947,11 @@ public class VibratorService extends IVibratorService.Stub private void startVibrationInnerLocked(Vibration vib) { Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationInnerLocked"); try { - long timeout = 0; mCurrentVibration = vib; if (vib.effect instanceof VibrationEffect.OneShot) { Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.effect; doVibratorOn(oneShot.getDuration(), oneShot.getAmplitude(), vib); - timeout = oneShot.getDuration() * ASYNC_TIMEOUT_MULTIPLIER; } else if (vib.effect instanceof VibrationEffect.Waveform) { // mThread better be null here. doCancelVibrate should always be // called before startNextVibrationLocked or startVibrationLocked. @@ -973,24 +960,13 @@ public class VibratorService extends IVibratorService.Stub mThread.start(); } else if (vib.effect instanceof VibrationEffect.Prebaked) { Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); - timeout = doVibratorPrebakedEffectLocked(vib); + doVibratorPrebakedEffectLocked(vib); } else if (vib.effect instanceof VibrationEffect.Composed) { Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); doVibratorComposedEffectLocked(vib); - // FIXME: We rely on the completion callback here, but I don't think we require that - // devices which support composition also support the completion callback. If we - // ever get a device that supports the former but not the latter, then we have no - // real way of knowing how long a given effect should last. - timeout = 10_000; } else { Slog.e(TAG, "Unknown vibration type, ignoring"); } - // Post extra runnable to ensure vibration will end even if the HAL or native controller - // never triggers the callback. - // TODO: Move ASYNC_TIMEOUT_MULTIPLIER here once native controller is fully integrated. - if (timeout > 0) { - mH.postDelayed(mVibrationEndRunnable, timeout); - } } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); } @@ -1354,7 +1330,7 @@ public class VibratorService extends IVibratorService.Stub } @GuardedBy("mLock") - private long doVibratorPrebakedEffectLocked(Vibration vib) { + private void doVibratorPrebakedEffectLocked(Vibration vib) { Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorPrebakedEffectLocked"); try { final VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.effect; @@ -1364,25 +1340,20 @@ public class VibratorService extends IVibratorService.Stub } // Input devices don't support prebaked effect, so skip trying it with them. if (!usingInputDeviceVibrators) { - long duration = mNativeWrapper.vibratorPerformEffect(prebaked.getId(), - prebaked.getEffectStrength(), vib, - hasCapability(IVibrator.CAP_PERFORM_CALLBACK)); - long timeout = duration; - if (hasCapability(IVibrator.CAP_PERFORM_CALLBACK)) { - timeout *= ASYNC_TIMEOUT_MULTIPLIER; - } - if (timeout > 0) { + long duration = mNativeWrapper.vibratorPerformEffect( + prebaked.getId(), prebaked.getEffectStrength(), vib); + if (duration > 0) { noteVibratorOnLocked(vib.uid, duration); - return timeout; + return; } } if (!prebaked.shouldFallback()) { - return 0; + return; } VibrationEffect effect = getFallbackEffect(prebaked.getId()); if (effect == null) { Slog.w(TAG, "Failed to play prebaked effect, no fallback"); - return 0; + return; } Vibration fallbackVib = new Vibration(vib.token, effect, vib.attrs, vib.uid, vib.opPkg, vib.reason + " (fallback)"); @@ -1390,7 +1361,7 @@ public class VibratorService extends IVibratorService.Stub linkVibration(fallbackVib); applyVibrationIntensityScalingLocked(fallbackVib, intensity); startVibrationInnerLocked(fallbackVib); - return 0; + return; } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); } @@ -1789,9 +1760,9 @@ public class VibratorService extends IVibratorService.Stub } /** Turns vibrator on to perform one of the supported effects. */ - public long vibratorPerformEffect(long effect, long strength, Vibration vibration, - boolean withCallback) { - return VibratorService.vibratorPerformEffect(effect, strength, vibration, withCallback); + public long vibratorPerformEffect(long effect, long strength, Vibration vibration) { + return VibratorService.vibratorPerformEffect( + mNativeControllerPtr, effect, strength, vibration); } /** Turns vibrator on to perform one of the supported composed effects. */ diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 3eb26de3a675..b83aa4fb4d86 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -694,12 +694,8 @@ public final class ActiveServices { } ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); - if (!r.mAllowWhileInUsePermissionInFgs) { - r.mAllowWhileInUsePermissionInFgs = - shouldAllowWhileInUsePermissionInFgsLocked(callingPackage, callingPid, - callingUid, service, r, allowBackgroundActivityStarts); - } - + setFgsRestrictionLocked(callingPackage, callingPid, + callingUid, service, r, allowBackgroundActivityStarts); return cmp; } @@ -1369,6 +1365,7 @@ public final class ActiveServices { + r.shortInstanceName); } } + boolean alreadyStartedOp = false; boolean stopProcStatsOp = false; if (r.fgRequired) { @@ -1415,6 +1412,24 @@ public final class ActiveServices { ignoreForeground = true; } + if (!ignoreForeground) { + if (!r.mAllowStartForeground) { + if (!r.mLoggedInfoAllowStartForeground) { + Slog.wtf(TAG, "Background started FGS " + + r.mInfoAllowStartForeground); + r.mLoggedInfoAllowStartForeground = true; + } + if (mAm.mConstants.mFlagFgsStartRestrictionEnabled) { + Slog.w(TAG, + "Service.startForeground() not allowed due to " + + " mAllowStartForeground false: service " + + r.shortInstanceName); + updateServiceForegroundLocked(r.app, true); + ignoreForeground = true; + } + } + } + // Apps under strict background restrictions simply don't get to have foreground // services, so now that we've enforced the startForegroundService() contract // we only do the machinery of making the service foreground when the app @@ -2067,12 +2082,7 @@ public final class ActiveServices { } } - if (!s.mAllowWhileInUsePermissionInFgs) { - s.mAllowWhileInUsePermissionInFgs = - shouldAllowWhileInUsePermissionInFgsLocked(callingPackage, - callingPid, callingUid, - service, s, false); - } + setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, s, false); if (s.app != null) { if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) { @@ -4840,21 +4850,48 @@ public final class ActiveServices { } /** - * Should allow while-in-use permissions in foreground service or not. - * while-in-use permissions in FGS started from background might be restricted. + * There are two FGS restrictions: + * In R, mAllowWhileInUsePermissionInFgs is to allow while-in-use permissions in foreground + * service or not. while-in-use permissions in FGS started from background might be restricted. + * In S, mAllowStartForeground is to allow FGS to startForeground or not. Service started + * from background may not become a FGS. * @param callingPackage caller app's package name. * @param callingUid caller app's uid. * @param intent intent to start/bind service. * @param r the service to start. * @return true if allow, false otherwise. */ - private boolean shouldAllowWhileInUsePermissionInFgsLocked(String callingPackage, + private void setFgsRestrictionLocked(String callingPackage, int callingPid, int callingUid, Intent intent, ServiceRecord r, boolean allowBackgroundActivityStarts) { - // Is the background FGS start restriction turned on? + // Check DeviceConfig flag. if (!mAm.mConstants.mFlagBackgroundFgsStartRestrictionEnabled) { - return true; + r.mAllowWhileInUsePermissionInFgs = true; + } + + if (!r.mAllowWhileInUsePermissionInFgs || !r.mAllowStartForeground) { + final boolean temp = shouldAllowFgsFeatureLocked(callingPackage, callingPid, + callingUid, intent, r, allowBackgroundActivityStarts); + if (!r.mAllowWhileInUsePermissionInFgs) { + r.mAllowWhileInUsePermissionInFgs = temp; + } + if (!r.mAllowStartForeground) { + r.mAllowStartForeground = temp; + } } + } + + /** + * Should allow FGS feature or not. + * @param callingPackage caller app's package name. + * @param callingUid caller app's uid. + * @param intent intent to start/bind service. + * @param r the service to start. + * @return true if allow, false otherwise. + */ + private boolean shouldAllowFgsFeatureLocked(String callingPackage, + int callingPid, int callingUid, Intent intent, ServiceRecord r, + boolean allowBackgroundActivityStarts) { // Is the allow activity background start flag on? if (allowBackgroundActivityStarts) { return true; @@ -4894,10 +4931,11 @@ public final class ActiveServices { } // Is the calling UID at PROCESS_STATE_TOP or above? - final boolean isCallingUidTopApp = appIsTopLocked(callingUid); - if (isCallingUidTopApp) { + final int uidState = mAm.getUidState(callingUid); + if (uidState <= ActivityManager.PROCESS_STATE_TOP) { return true; } + // Does the calling UID have any visible activity? final boolean isCallingUidVisible = mAm.mAtmInternal.isUidForeground(callingUid); if (isCallingUidVisible) { @@ -4915,6 +4953,19 @@ public final class ActiveServices { if (isDeviceOwner) { return true; } + + final String info = + "[callingPackage: " + callingPackage + + "; callingUid: " + callingUid + + "; uidState: " + ProcessList.makeProcStateString(uidState) + + "; intent: " + intent + + "; targetSdkVersion:" + r.appInfo.targetSdkVersion + + "]"; + if (!info.equals(r.mInfoAllowStartForeground)) { + r.mLoggedInfoAllowStartForeground = false; + r.mInfoAllowStartForeground = info; + } + return false; } } diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 775119c18037..e9539be8b0d5 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -144,6 +144,13 @@ final class ActivityManagerConstants extends ContentObserver { private static final String KEY_DEFAULT_BACKGROUND_FGS_STARTS_RESTRICTION_ENABLED = "default_background_fgs_starts_restriction_enabled"; + /** + * Default value for mFlagFgsStartRestrictionEnabled if not explicitly set in + * Settings.Global. + */ + private static final String KEY_DEFAULT_FGS_STARTS_RESTRICTION_ENABLED = + "default_fgs_starts_restriction_enabled"; + // Maximum number of cached processes we will allow. public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES; @@ -293,6 +300,11 @@ final class ActivityManagerConstants extends ContentObserver { // started, the restriction is on while-in-use permissions.) volatile boolean mFlagBackgroundFgsStartRestrictionEnabled = true; + // Indicates whether the foreground service background start restriction is enabled. + // When the restriction is enabled, service is not allowed to startForeground from background + // at all. + volatile boolean mFlagFgsStartRestrictionEnabled = false; + private final ActivityManagerService mService; private ContentResolver mResolver; private final KeyValueListParser mParser = new KeyValueListParser(','); @@ -436,6 +448,9 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_DEFAULT_BACKGROUND_FGS_STARTS_RESTRICTION_ENABLED: updateBackgroundFgsStartsRestriction(); break; + case KEY_DEFAULT_FGS_STARTS_RESTRICTION_ENABLED: + updateFgsStartsRestriction(); + break; case KEY_OOMADJ_UPDATE_POLICY: updateOomAdjUpdatePolicy(); break; @@ -659,6 +674,7 @@ final class ActivityManagerConstants extends ContentObserver { mFlagForegroundServiceStartsLoggingEnabled = Settings.Global.getInt(mResolver, Settings.Global.FOREGROUND_SERVICE_STARTS_LOGGING_ENABLED, 1) == 1; } + private void updateBackgroundFgsStartsRestriction() { mFlagBackgroundFgsStartRestrictionEnabled = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, @@ -666,6 +682,13 @@ final class ActivityManagerConstants extends ContentObserver { /*defaultValue*/ true); } + private void updateFgsStartsRestriction() { + mFlagFgsStartRestrictionEnabled = DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_DEFAULT_FGS_STARTS_RESTRICTION_ENABLED, + /*defaultValue*/ false); + } + private void updateOomAdjUpdatePolicy() { OOMADJ_UPDATE_QUICK = DeviceConfig.getInt( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index b62ff1c26f8f..a838aadc404e 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -14470,7 +14470,7 @@ public class ActivityManagerService extends IActivityManager.Stub resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions, appOp, bOptions, ordered, sticky, callingPid, callingUid, realCallingUid, realCallingPid, userId, false /* allowBackgroundActivityStarts */, - null /* tokenNeededForBackgroundActivityStarts */, null /* broadcastWhitelist */); + null /* tokenNeededForBackgroundActivityStarts */, null /* broadcastAllowList */); } @GuardedBy("this") @@ -15314,7 +15314,7 @@ public class ActivityManagerService extends IActivityManager.Stub OP_NONE, bOptions, serialized, sticky, -1, uid, realCallingUid, realCallingPid, userId, allowBackgroundActivityStarts, backgroundActivityStartsToken, - null /*broadcastWhitelist*/); + null /* broadcastAllowList */); } finally { Binder.restoreCallingIdentity(origId); } diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index 4a2703056871..66677b67b6aa 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -146,6 +146,12 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN // the most recent package that start/bind this service. String mRecentCallingPackage; + // allow the service becomes foreground service? Service started from background may not be + // allowed to become a foreground service. + boolean mAllowStartForeground; + String mInfoAllowStartForeground; + boolean mLoggedInfoAllowStartForeground; + String stringName; // caching of toString private int lastStartId; // identifier of most recent start request. @@ -408,6 +414,10 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN pw.println(mAllowWhileInUsePermissionInFgs); pw.print(prefix); pw.print("recentCallingPackage="); pw.println(mRecentCallingPackage); + pw.print(prefix); pw.print("allowStartForeground="); + pw.println(mAllowStartForeground); + pw.print(prefix); pw.print("infoAllowStartForeground="); + pw.println(mInfoAllowStartForeground); if (delayed) { pw.print(prefix); pw.print("delayed="); pw.println(delayed); } diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 0658e8139cc2..7420e0a6e828 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -1630,7 +1630,7 @@ class UserController implements Handler.Callback { UserInfo currentUserInfo = getUserInfo(currentUserId); Pair<UserInfo, UserInfo> userNames = new Pair<>(currentUserInfo, targetUserInfo); mUiHandler.removeMessages(START_USER_SWITCH_UI_MSG); - mUiHandler.sendMessage(mHandler.obtainMessage( + mUiHandler.sendMessage(mUiHandler.obtainMessage( START_USER_SWITCH_UI_MSG, userNames)); } else { mHandler.removeMessages(START_USER_SWITCH_FG_MSG); @@ -2887,13 +2887,18 @@ class UserController implements Handler.Callback { void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser, String switchingFromSystemUserMessage, String switchingToSystemUserMessage) { - if (!mService.mContext.getPackageManager() + if (mService.mContext.getPackageManager() .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { - final Dialog d = new UserSwitchingDialog(mService, mService.mContext, fromUser, - toUser, true /* above system */, switchingFromSystemUserMessage, - switchingToSystemUserMessage); - d.show(); - } + // config_customUserSwitchUi is set to true on Automotive as CarSystemUI is + // responsible to show the UI; OEMs should not change that, but if they do, we + // should at least warn the user... + Slog.w(TAG, "Showing user switch dialog on UserController, it could cause a race " + + "condition if it's shown by CarSystemUI as well"); + } + final Dialog d = new UserSwitchingDialog(mService, mService.mContext, fromUser, + toUser, true /* above system */, switchingFromSystemUserMessage, + switchingToSystemUserMessage); + d.show(); } void reportGlobalUsageEventLocked(int event) { diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index b94396634530..23b09294260c 100755 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -1282,6 +1282,7 @@ public class AudioService extends IAudioService.Stub } if (isPlatformTelevision()) { + checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI, caller); synchronized (mHdmiClientLock) { if (mHdmiManager != null && mHdmiPlaybackClient != null) { updateHdmiCecSinkLocked(mHdmiCecSink | false); @@ -1301,54 +1302,22 @@ public class AudioService extends IAudioService.Stub } } - /** - * Update volume states for the given device. - * - * This will initialize the volume index if no volume index is available. - * If the device is the currently routed device, fixed/full volume policies will be applied. - * - * @param device a single audio device, ensure that this is not a devices bitmask - * @param caller caller of this method - */ - private void updateVolumeStatesForAudioDevice(int device, String caller) { + private void checkAddAllFixedVolumeDevices(int device, String caller) { final int numStreamTypes = AudioSystem.getNumStreamTypes(); for (int streamType = 0; streamType < numStreamTypes; streamType++) { - updateVolumeStates(device, streamType, caller); - } - } - - /** - * Update volume states for the given device and given stream. - * - * This will initialize the volume index if no volume index is available. - * If the device is the currently routed device, fixed/full volume policies will be applied. - * - * @param device a single audio device, ensure that this is not a devices bitmask - * @param streamType streamType to be updated - * @param caller caller of this method - */ - private void updateVolumeStates(int device, int streamType, String caller) { - if (!mStreamStates[streamType].hasIndexForDevice(device)) { - // set the default value, if device is affected by a full/fix/abs volume rule, it - // will taken into account in checkFixedVolumeDevices() - mStreamStates[streamType].setIndex( - mStreamStates[mStreamVolumeAlias[streamType]] - .getIndex(AudioSystem.DEVICE_OUT_DEFAULT), - device, caller, true /*hasModifyAudioSettings*/); - } - - // Check if device to be updated is routed for the given audio stream - List<AudioDeviceAttributes> devicesForAttributes = getDevicesForAttributes( - new AudioAttributes.Builder().setInternalLegacyStreamType(streamType).build()); - for (AudioDeviceAttributes deviceAttributes : devicesForAttributes) { - if (deviceAttributes.getType() == AudioDeviceInfo.convertInternalDeviceToDeviceType( - device)) { - mStreamStates[streamType].checkFixedVolumeDevices(); + if (!mStreamStates[streamType].hasIndexForDevice(device)) { + // set the default value, if device is affected by a full/fix/abs volume rule, it + // will taken into account in checkFixedVolumeDevices() + mStreamStates[streamType].setIndex( + mStreamStates[mStreamVolumeAlias[streamType]] + .getIndex(AudioSystem.DEVICE_OUT_DEFAULT), + device, caller, true /*hasModifyAudioSettings*/); + } + mStreamStates[streamType].checkFixedVolumeDevices(); - // Unmute streams if required if device is full volume - if (isStreamMute(streamType) && mFullVolumeDevices.contains(device)) { - mStreamStates[streamType].mute(false); - } + // Unmute streams if device is full volume + if (mFullVolumeDevices.contains(device)) { + mStreamStates[streamType].mute(false); } } } @@ -4932,15 +4901,7 @@ public class AudioService extends IAudioService.Stub synchronized (VolumeStreamState.class) { for (int stream = 0; stream < mStreamStates.length; stream++) { if (stream != skipStream) { - int devices = mStreamStates[stream].observeDevicesForStream_syncVSS( - false /*checkOthers*/); - - Set<Integer> devicesSet = AudioSystem.generateAudioDeviceTypesSet(devices); - for (Integer device : devicesSet) { - // Update volume states for devices routed for the stream - updateVolumeStates(device, stream, - "AudioService#observeDevicesForStreams"); - } + mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/); } } } @@ -5009,7 +4970,7 @@ public class AudioService extends IAudioService.Stub + Integer.toHexString(audioSystemDeviceOut) + " from:" + caller)); // make sure we have a volume entry for this device, and that volume is updated according // to volume behavior - updateVolumeStatesForAudioDevice(audioSystemDeviceOut, "setDeviceVolumeBehavior:" + caller); + checkAddAllFixedVolumeDevices(audioSystemDeviceOut, "setDeviceVolumeBehavior:" + caller); } /** @@ -7231,9 +7192,10 @@ public class AudioService extends IAudioService.Stub // HDMI output removeAudioSystemDeviceOutFromFullVolumeDevices(AudioSystem.DEVICE_OUT_HDMI); } - updateVolumeStatesForAudioDevice(AudioSystem.DEVICE_OUT_HDMI, - "HdmiPlaybackClient.DisplayStatusCallback"); } + + checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI, + "HdmiPlaybackClient.DisplayStatusCallback"); } private class MyHdmiControlStatusChangeListenerCallback diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 397358b44362..dab8c7fc9d48 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -30,8 +30,6 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUST import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL; import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL; import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL; -import static android.view.Surface.ROTATION_270; -import static android.view.Surface.ROTATION_90; import android.Manifest; import android.annotation.NonNull; @@ -46,7 +44,6 @@ import android.content.res.TypedArray; import android.database.ContentObserver; import android.graphics.ColorSpace; import android.graphics.Point; -import android.graphics.Rect; import android.hardware.SensorManager; import android.hardware.display.AmbientBrightnessDayStats; import android.hardware.display.BrightnessChangeEvent; @@ -104,7 +101,6 @@ import com.android.server.AnimationThread; import com.android.server.DisplayThread; import com.android.server.LocalServices; import com.android.server.SystemService; -import com.android.server.SystemService.TargetUser; import com.android.server.UiThread; import com.android.server.wm.SurfaceAnimationThread; import com.android.server.wm.WindowManagerInternal; @@ -1394,9 +1390,13 @@ public final class DisplayManagerService extends SystemService { } final DisplayInfo displayInfo = logicalDisplay.getDisplayInfoLocked(); - return SurfaceControl.screenshotToBufferWithSecureLayersUnsafe(token, new Rect(), - displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight(), - false /* useIdentityTransform */, 0 /* rotation */); + final SurfaceControl.DisplayCaptureArgs captureArgs = + new SurfaceControl.DisplayCaptureArgs.Builder(token) + .setSize(displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight()) + .setUseIdentityTransform(true) + .setCaptureSecureLayers(true) + .build(); + return SurfaceControl.captureDisplay(captureArgs); } } @@ -1406,30 +1406,11 @@ public final class DisplayManagerService extends SystemService { if (token == null) { return null; } - final LogicalDisplay logicalDisplay = mLogicalDisplays.get(displayId); - if (logicalDisplay == null) { - return null; - } - - final DisplayInfo displayInfo = logicalDisplay.getDisplayInfoLocked(); - // Takes screenshot based on current device orientation. - final Display display = DisplayManagerGlobal.getInstance() - .getRealDisplay(displayId); - if (display == null) { - return null; - } - final Point displaySize = new Point(); - display.getRealSize(displaySize); - - int rotation = displayInfo.rotation; - // TODO (b/153382624) : This workaround solution would be removed after - // SurfaceFlinger fixes the inconsistency with rotation direction issue. - if (rotation == ROTATION_90 || rotation == ROTATION_270) { - rotation = (rotation == ROTATION_90) ? ROTATION_270 : ROTATION_90; - } - return SurfaceControl.screenshotToBuffer(token, new Rect(), displaySize.x, - displaySize.y, false /* useIdentityTransform */, rotation /* rotation */); + final SurfaceControl.DisplayCaptureArgs captureArgs = + new SurfaceControl.DisplayCaptureArgs.Builder(token) + .build(); + return SurfaceControl.captureDisplay(captureArgs); } } diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java index 7bbcdaa2d473..6672daa6f17a 100644 --- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java +++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java @@ -949,7 +949,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem if (debug) { Slog.d(mTag, "Eagerly recreating service for user " + userId); } - getServiceForUserLocked(userId); + updateCachedServiceLocked(userId); } } onServicePackageRestartedLocked(userId); diff --git a/services/core/java/com/android/server/location/LocationProviderManager.java b/services/core/java/com/android/server/location/LocationProviderManager.java index d4f8c7e855b9..c3532a84c42d 100644 --- a/services/core/java/com/android/server/location/LocationProviderManager.java +++ b/services/core/java/com/android/server/location/LocationProviderManager.java @@ -1615,7 +1615,7 @@ class LocationProviderManager extends case LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF: // fall through case LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF: - updateService(); + updateRegistrations(registration -> true); break; default: break; diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java index 8004ec70aaf3..850cf7f4b7ce 100644 --- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java @@ -49,8 +49,6 @@ import android.os.Looper; import android.os.Message; import android.os.PersistableBundle; import android.os.PowerManager; -import android.os.PowerManager.ServiceType; -import android.os.PowerSaveState; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; @@ -486,10 +484,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements deviceIdleService.unregisterStationaryListener( mDeviceIdleStationaryListener); } - // Intentional fall-through. - case PowerManager.ACTION_POWER_SAVE_MODE_CHANGED: - case Intent.ACTION_SCREEN_OFF: - case Intent.ACTION_SCREEN_ON: // Call updateLowPowerMode on handler thread so it's always called from the // same thread. mHandler.sendEmptyMessage(UPDATE_LOW_POWER_MODE); @@ -554,15 +548,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private void updateLowPowerMode() { // Disable GPS if we are in device idle mode and the device is stationary. boolean disableGpsForPowerManager = mPowerManager.isDeviceIdleMode() && mIsDeviceStationary; - final PowerSaveState result = mPowerManager.getPowerSaveState(ServiceType.LOCATION); - switch (result.locationMode) { - case PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF: - case PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF: - // If we are in battery saver mode and the screen is off, disable GPS. - disableGpsForPowerManager |= - result.batterySaverEnabled && !mPowerManager.isInteractive(); - break; - } if (disableGpsForPowerManager != mDisableGpsForPowerManager) { mDisableGpsForPowerManager = disableGpsForPowerManager; updateEnabled(); @@ -1959,10 +1944,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(ALARM_WAKEUP); intentFilter.addAction(ALARM_TIMEOUT); - intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED); intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); - intentFilter.addAction(Intent.ACTION_SCREEN_OFF); - intentFilter.addAction(Intent.ACTION_SCREEN_ON); intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); intentFilter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this); diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index e2f70e320cb8..eb4ab1ceac28 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -1937,7 +1937,8 @@ public class MediaSessionService extends SystemService implements Monitor { // Context#getPackageName() for getting package name that matches with the PID/UID, // but it doesn't tell which package has created the MediaController, so useless. return hasMediaControlPermission(controllerPid, controllerUid) - || hasEnabledNotificationListener(userId, controllerPackageName, uid); + || hasEnabledNotificationListener( + userId, controllerPackageName, controllerUid); } finally { Binder.restoreCallingIdentity(token); } @@ -2001,21 +2002,21 @@ public class MediaSessionService extends SystemService implements Monitor { return resolvedUserId; } - private boolean hasEnabledNotificationListener(int resolvedUserId, String packageName, - int uid) { - // TODO: revisit this checking code - // You may not access another user's content as an enabled listener. - final int userId = UserHandle.getUserHandleForUid(resolvedUserId).getIdentifier(); - if (resolvedUserId != userId) { + private boolean hasEnabledNotificationListener(int callingUserId, + String controllerPackageName, int controllerUid) { + int controllerUserId = UserHandle.getUserHandleForUid(controllerUid).getIdentifier(); + if (callingUserId != controllerUserId) { + // Enabled notification listener only works within the same user. return false; } - if (mNotificationManager.hasEnabledNotificationListener(packageName, - UserHandle.getUserHandleForUid(uid))) { + + if (mNotificationManager.hasEnabledNotificationListener(controllerPackageName, + UserHandle.getUserHandleForUid(controllerUid))) { return true; } if (DEBUG) { - Log.d(TAG, packageName + " (uid=" + uid + ") doesn't have an enabled " - + "notification listener"); + Log.d(TAG, controllerPackageName + " (uid=" + controllerUid + + ") doesn't have an enabled notification listener"); } return false; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index a874f612e106..0d1c00dfe035 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -2232,7 +2232,7 @@ public class PackageManagerService extends IPackageManager.Stub sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, 0 /*flags*/, installerPackageName, null /*finishedReceiver*/, - updateUserIds, instantUserIds, null /* broadcastWhitelist */); + updateUserIds, instantUserIds, null /* broadcastAllowList */); } // if the required verifier is defined, but, is not the installer of record // for the package, it gets notified @@ -2242,7 +2242,7 @@ public class PackageManagerService extends IPackageManager.Stub sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, 0 /*flags*/, mRequiredVerifierPackage, null /*finishedReceiver*/, - updateUserIds, instantUserIds, null /* broadcastWhitelist */); + updateUserIds, instantUserIds, null /* broadcastAllowList */); } // If package installer is defined, notify package installer about new // app installed @@ -2250,7 +2250,7 @@ public class PackageManagerService extends IPackageManager.Stub sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND /*flags*/, mRequiredInstallerPackage, null /*finishedReceiver*/, - firstUserIds, instantUserIds, null /* broadcastWhitelist */); + firstUserIds, instantUserIds, null /* broadcastAllowList */); } // Send replaced for users that don't see the package for the first time @@ -2263,19 +2263,19 @@ public class PackageManagerService extends IPackageManager.Stub sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras, 0 /*flags*/, installerPackageName, null /*finishedReceiver*/, - updateUserIds, instantUserIds, null /*broadcastWhitelist*/); + updateUserIds, instantUserIds, null /*broadcastAllowList*/); } if (notifyVerifier) { sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras, 0 /*flags*/, mRequiredVerifierPackage, null /*finishedReceiver*/, - updateUserIds, instantUserIds, null /*broadcastWhitelist*/); + updateUserIds, instantUserIds, null /*broadcastAllowList*/); } sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null /*package*/, null /*extras*/, 0 /*flags*/, packageName /*targetPackage*/, null /*finishedReceiver*/, updateUserIds, instantUserIds, - null /*broadcastWhitelist*/); + null /*broadcastAllowList*/); } else if (launchedForRestore && !res.pkg.isSystem()) { // First-install and we did a restore, so we're responsible for the // first-launch broadcast. @@ -14627,7 +14627,7 @@ public class PackageManagerService extends IPackageManager.Stub private void sendFirstLaunchBroadcast(String pkgName, String installerPkg, int[] userIds, int[] instantUserIds) { sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH, pkgName, null, 0, - installerPkg, null, userIds, instantUserIds, null /* broadcastWhitelist */); + installerPkg, null, userIds, instantUserIds, null /* broadcastAllowList */); } private abstract class HandlerParams { @@ -18730,14 +18730,14 @@ public class PackageManagerService extends IPackageManager.Stub packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, removedPackage, extras, 0, null /*targetPackage*/, null, null, null, broadcastAllowList); packageSender.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, 0, - removedPackage, null, null, null, null /* broadcastWhitelist */); + removedPackage, null, null, null, null /* broadcastAllowList */); if (installerPackageName != null) { packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, removedPackage, extras, 0 /*flags*/, - installerPackageName, null, null, null, null /* broadcastWhitelist */); + installerPackageName, null, null, null, null /* broadcastAllowList */); packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, removedPackage, extras, 0 /*flags*/, - installerPackageName, null, null, null, null /* broadcastWhitelist */); + installerPackageName, null, null, null, null /* broadcastAllowList */); } } @@ -25700,9 +25700,9 @@ interface PackageSender { * @param instantUserIds User IDs where the action occurred on an instant application */ void sendPackageBroadcast(final String action, final String pkg, - final Bundle extras, final int flags, final String targetPkg, - final IIntentReceiver finishedReceiver, final int[] userIds, int[] instantUserIds, - @Nullable SparseArray<int[]> broadcastWhitelist); + final Bundle extras, final int flags, final String targetPkg, + final IIntentReceiver finishedReceiver, final int[] userIds, int[] instantUserIds, + @Nullable SparseArray<int[]> broadcastAllowList); void sendPackageAddedForNewUsers(String packageName, boolean sendBootCompleted, boolean includeStopped, int appId, int[] userIds, int[] instantUserIds, int dataLoaderType); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index bf9506ad51f1..9dda3812fccf 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -87,6 +87,7 @@ import android.stats.devicepolicy.DevicePolicyEnums; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; +import android.util.IndentingPrintWriter; import android.util.IntArray; import android.util.Slog; import android.util.SparseArray; @@ -103,7 +104,6 @@ import com.android.internal.os.BackgroundThread; import com.android.internal.util.DumpUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.FrameworkStatsLog; -import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import com.android.internal.widget.LockPatternUtils; @@ -4786,6 +4786,7 @@ public class UserManagerService extends IUserManager.Stub { } } + pw.println(); pw.println("Device properties:"); pw.println(" Device owner id:" + mDeviceOwnerUserId); pw.println(); @@ -4814,12 +4815,9 @@ public class UserManagerService extends IUserManager.Stub { } pw.println(']'); } - synchronized (mUsersLock) { - pw.println(); - pw.print("Cached user IDs: "); + pw.print(" Cached user IDs: "); pw.println(Arrays.toString(mUserIds)); - pw.println(); } } // synchronized (mPackagesLock) @@ -4844,9 +4842,17 @@ public class UserManagerService extends IUserManager.Stub { mUserTypes.valueAt(i).dump(pw, " "); } - // Dump package whitelist - pw.println(); - mSystemPackageInstaller.dump(pw); + // TODO: create IndentingPrintWriter at the beginning of dump() and use the proper + // indentation methods instead of explicit printing " " + try (IndentingPrintWriter ipw = new IndentingPrintWriter(pw)) { + + // Dump SystemPackageInstaller info + ipw.println(); + mSystemPackageInstaller.dump(ipw); + + // NOTE: pw's not available after this point as it's auto-closed by ipw, so new dump + // statements should use ipw below + } } private static void dumpTimeAgo(PrintWriter pw, StringBuilder sb, long nowTime, long time) { diff --git a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java index 492b84a0a84b..b95404febf72 100644 --- a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java +++ b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java @@ -28,15 +28,14 @@ import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; import android.util.DebugUtils; +import android.util.IndentingPrintWriter; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.IndentingPrintWriter; import com.android.server.LocalServices; import com.android.server.SystemConfig; import com.android.server.pm.parsing.pkg.AndroidPackage; -import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -723,13 +722,7 @@ class UserSystemPackageInstaller { return userTypeList; } - void dump(PrintWriter pw) { - try (IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ")) { - dumpIndented(ipw); - } - } - - private void dumpIndented(IndentingPrintWriter pw) { + void dump(IndentingPrintWriter pw) { final int mode = getWhitelistMode(); pw.println("Whitelisted packages per user type"); diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 03771be0ce7c..63aa80e8269a 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -83,6 +83,7 @@ import android.content.pm.PackageParser; import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; +import android.content.pm.UserInfo; import android.content.pm.parsing.component.ParsedPermission; import android.content.pm.parsing.component.ParsedPermissionGroup; import android.content.pm.permission.SplitPermissionInfoParcelable; @@ -120,6 +121,7 @@ import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; +import android.util.TimingsTraceLog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -2521,12 +2523,12 @@ public class PermissionManagerService extends IPermissionManager.Stub { final PermissionsState permissionsState = ps.getPermissionsState(); - final int[] currentUserIds = UserManagerService.getInstance().getUserIds(); + final int[] userIds = getAllUserIds(); boolean runtimePermissionsRevoked = false; int[] updatedUserIds = EMPTY_INT_ARRAY; - for (int userId : currentUserIds) { + for (int userId : userIds) { if (permissionsState.isMissing(userId)) { Collection<String> requestedPermissions; int targetSdkVersion; @@ -2592,7 +2594,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { // runtime and revocation of a runtime from a shared user. synchronized (mLock) { updatedUserIds = revokeUnusedSharedUserPermissionsLocked(ps.getSharedUser(), - currentUserIds); + userIds); if (!ArrayUtils.isEmpty(updatedUserIds)) { runtimePermissionsRevoked = true; } @@ -2747,7 +2749,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { // a runtime permission being downgraded to an install one. // Also in permission review mode we keep dangerous permissions // for legacy apps - for (int userId : currentUserIds) { + for (int userId : userIds) { if (origPermissions.getRuntimePermissionState( perm, userId) != null) { // Revoke the runtime permission and clear the flags. @@ -2770,7 +2772,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { boolean hardRestricted = bp.isHardRestricted(); boolean softRestricted = bp.isSoftRestricted(); - for (int userId : currentUserIds) { + for (int userId : userIds) { // If permission policy is not ready we don't deal with restricted // permissions as the policy may whitelist some permissions. Once // the policy is initialized we would re-evaluate permissions. @@ -2909,7 +2911,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { boolean hardRestricted = bp.isHardRestricted(); boolean softRestricted = bp.isSoftRestricted(); - for (int userId : currentUserIds) { + for (int userId : userIds) { // If permission policy is not ready we don't deal with restricted // permissions as the policy may whitelist some permissions. Once // the policy is initialized we would re-evaluate permissions. @@ -3061,10 +3063,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { synchronized (mLock) { updatedUserIds = revokePermissionsNoLongerImplicitLocked(permissionsState, pkg, - currentUserIds, updatedUserIds); + userIds, updatedUserIds); updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origPermissions, - permissionsState, pkg, newImplicitPermissions, currentUserIds, updatedUserIds); - updatedUserIds = checkIfLegacyStorageOpsNeedToBeUpdated(pkg, replace, currentUserIds, + permissionsState, pkg, newImplicitPermissions, userIds, updatedUserIds); + updatedUserIds = checkIfLegacyStorageOpsNeedToBeUpdated(pkg, replace, userIds, updatedUserIds); } @@ -3081,6 +3083,25 @@ public class PermissionManagerService extends IPermissionManager.Stub { } /** + * Returns all relevant user ids. This list include the current set of created user ids as well + * as pre-created user ids. + * @return user ids for created users and pre-created users + */ + private int[] getAllUserIds() { + final TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER); + t.traceBegin("getAllUserIds"); + List<UserInfo> users = UserManagerService.getInstance().getUsers( + /*excludePartial=*/ true, /*excludeDying=*/ true, /*excludePreCreated=*/ false); + int size = users.size(); + final int[] userIds = new int[size]; + for (int i = 0; i < size; i++) { + userIds[i] = users.get(i).id; + } + t.traceEnd(); + return userIds; + } + + /** * Revoke permissions that are not implicit anymore and that have * {@link PackageManager#FLAG_PERMISSION_REVOKE_WHEN_REQUESTED} set. * diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index fa3bcb6b98eb..548cd70de4d1 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -450,7 +450,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { volatile int mPendingWakeKey = PENDING_KEY_NULL; int mRecentAppsHeldModifiers; - boolean mLanguageSwitchKeyPressed; int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT; boolean mHaveBuiltInKeyboard; @@ -2938,12 +2937,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction); return -1; } - if (mLanguageSwitchKeyPressed && !down - && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH - || keyCode == KeyEvent.KEYCODE_SPACE)) { - mLanguageSwitchKeyPressed = false; - return -1; - } if (isValidGlobalKey(keyCode) && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) { diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java index 2a74b3d23829..5aedfc19028b 100644 --- a/services/core/java/com/android/server/slice/SliceManagerService.java +++ b/services/core/java/com/android/server/slice/SliceManagerService.java @@ -28,8 +28,6 @@ import static android.os.Process.SYSTEM_UID; import android.Manifest.permission; import android.annotation.NonNull; import android.app.AppOpsManager; -import android.app.role.OnRoleHoldersChangedListener; -import android.app.role.RoleManager; import android.app.slice.ISliceManager; import android.app.slice.SliceSpec; import android.app.usage.UsageStatsManagerInternal; @@ -41,9 +39,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; -import android.content.pm.PackageManagerInternal; import android.content.pm.ProviderInfo; -import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Binder; import android.os.Handler; @@ -65,7 +61,6 @@ import com.android.internal.app.AssistUtils; import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.SystemService; -import com.android.server.SystemService.TargetUser; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -77,10 +72,7 @@ import java.io.ByteArrayOutputStream; import java.io.FileDescriptor; import java.io.IOException; import java.util.ArrayList; -import java.util.List; import java.util.Objects; -import java.util.concurrent.Executor; -import java.util.function.Supplier; public class SliceManagerService extends ISliceManager.Stub { @@ -88,16 +80,13 @@ public class SliceManagerService extends ISliceManager.Stub { private final Object mLock = new Object(); private final Context mContext; - private final PackageManagerInternal mPackageManagerInternal; private final AppOpsManager mAppOps; private final AssistUtils mAssistUtils; @GuardedBy("mLock") private final ArrayMap<Uri, PinnedSliceState> mPinnedSlicesByUri = new ArrayMap<>(); @GuardedBy("mLock") - private final SparseArray<PackageMatchingCache> mAssistantLookup = new SparseArray<>(); - @GuardedBy("mLock") - private final SparseArray<PackageMatchingCache> mHomeLookup = new SparseArray<>(); + private final SparseArray<String> mLastAssistantPackage = new SparseArray<>(); private final Handler mHandler; private final SlicePermissionManager mPermissions; @@ -110,8 +99,6 @@ public class SliceManagerService extends ISliceManager.Stub { @VisibleForTesting SliceManagerService(Context context, Looper looper) { mContext = context; - mPackageManagerInternal = Objects.requireNonNull( - LocalServices.getService(PackageManagerInternal.class)); mAppOps = context.getSystemService(AppOpsManager.class); mAssistUtils = new AssistUtils(context); mHandler = new Handler(looper); @@ -124,7 +111,6 @@ public class SliceManagerService extends ISliceManager.Stub { filter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addDataScheme("package"); - mRoleObserver = new RoleObserver(); mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler); } @@ -174,8 +160,7 @@ public class SliceManagerService extends ISliceManager.Stub { mHandler.post(() -> { if (slicePkg != null && !Objects.equals(pkg, slicePkg)) { mAppUsageStats.reportEvent(slicePkg, user, - isAssistant(pkg, user) || isDefaultHomeApp(pkg, user) - ? SLICE_PINNED_PRIV : SLICE_PINNED); + isAssistant(pkg, user) ? SLICE_PINNED_PRIV : SLICE_PINNED); } }); } @@ -440,38 +425,19 @@ public class SliceManagerService extends ISliceManager.Stub { private boolean hasFullSliceAccess(String pkg, int userId) { long ident = Binder.clearCallingIdentity(); try { - boolean ret = isDefaultHomeApp(pkg, userId) || isAssistant(pkg, userId) - || isGrantedFullAccess(pkg, userId); - return ret; + return isAssistant(pkg, userId) || isGrantedFullAccess(pkg, userId); } finally { Binder.restoreCallingIdentity(ident); } } private boolean isAssistant(String pkg, int userId) { - return getAssistantMatcher(userId).matches(pkg); - } - - private boolean isDefaultHomeApp(String pkg, int userId) { - return getHomeMatcher(userId).matches(pkg); - } - - private PackageMatchingCache getAssistantMatcher(int userId) { - PackageMatchingCache matcher = mAssistantLookup.get(userId); - if (matcher == null) { - matcher = new PackageMatchingCache(() -> getAssistant(userId)); - mAssistantLookup.put(userId, matcher); - } - return matcher; - } - - private PackageMatchingCache getHomeMatcher(int userId) { - PackageMatchingCache matcher = mHomeLookup.get(userId); - if (matcher == null) { - matcher = new PackageMatchingCache(() -> getDefaultHome(userId)); - mHomeLookup.put(userId, matcher); + if (pkg == null) return false; + if (!pkg.equals(mLastAssistantPackage.get(userId))) { + // Failed on cached value, try updating. + mLastAssistantPackage.put(userId, getAssistant(userId)); } - return matcher; + return pkg.equals(mLastAssistantPackage.get(userId)); } private String getAssistant(int userId) { @@ -482,111 +448,6 @@ public class SliceManagerService extends ISliceManager.Stub { return cn.getPackageName(); } - /** - * A cached value of the default home app - */ - private String mCachedDefaultHome = null; - - // Based on getDefaultHome in ShortcutService. - // TODO: Unify if possible - @VisibleForTesting - protected String getDefaultHome(int userId) { - - // Set VERIFY to true to run the cache in "shadow" mode for cache - // testing. Do not commit set to true; - final boolean VERIFY = false; - - if (mCachedDefaultHome != null) { - if (!VERIFY) { - return mCachedDefaultHome; - } - } - - final long token = Binder.clearCallingIdentity(); - try { - final List<ResolveInfo> allHomeCandidates = new ArrayList<>(); - - // Default launcher from package manager. - final ComponentName defaultLauncher = mPackageManagerInternal - .getHomeActivitiesAsUser(allHomeCandidates, userId); - - ComponentName detected = defaultLauncher; - - // Cache the default launcher. It is not a problem if the - // launcher is null - eventually, the default launcher will be - // set to something non-null. - mCachedDefaultHome = ((detected != null) ? detected.getPackageName() : null); - - if (detected == null) { - // If we reach here, that means it's the first check since the user was created, - // and there's already multiple launchers and there's no default set. - // Find the system one with the highest priority. - // (We need to check the priority too because of FallbackHome in Settings.) - // If there's no system launcher yet, then no one can access slices, until - // the user explicitly sets one. - final int size = allHomeCandidates.size(); - - int lastPriority = Integer.MIN_VALUE; - for (int i = 0; i < size; i++) { - final ResolveInfo ri = allHomeCandidates.get(i); - if (!ri.activityInfo.applicationInfo.isSystemApp()) { - continue; - } - if (ri.priority < lastPriority) { - continue; - } - detected = ri.activityInfo.getComponentName(); - lastPriority = ri.priority; - } - } - final String ret = ((detected != null) ? detected.getPackageName() : null); - if (VERIFY) { - if (mCachedDefaultHome != null && !mCachedDefaultHome.equals(ret)) { - Slog.e(TAG, "getDefaultHome() cache failure, is " + - mCachedDefaultHome + " should be " + ret); - } - } - return ret; - } finally { - Binder.restoreCallingIdentity(token); - } - } - - public void invalidateCachedDefaultHome() { - mCachedDefaultHome = null; - } - - /** - * Listen for changes in the roles, and invalidate the cached default - * home as necessary. - */ - private RoleObserver mRoleObserver; - - class RoleObserver implements OnRoleHoldersChangedListener { - private RoleManager mRm; - private final Executor mExecutor; - - RoleObserver() { - mExecutor = mContext.getMainExecutor(); - register(); - } - - public void register() { - mRm = mContext.getSystemService(RoleManager.class); - if (mRm != null) { - mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.ALL); - invalidateCachedDefaultHome(); - } - } - - @Override - public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) { - if (RoleManager.ROLE_HOME.equals(roleName)) { - invalidateCachedDefaultHome(); - } - } - } - private boolean isGrantedFullAccess(String pkg, int userId) { return mPermissions.hasFullAccess(pkg, userId); } @@ -635,30 +496,6 @@ public class SliceManagerService extends ISliceManager.Stub { return mPermissions.getAllPackagesGranted(pkg); } - /** - * Holder that caches a package that has access to a slice. - */ - static class PackageMatchingCache { - - private final Supplier<String> mPkgSource; - private String mCurrentPkg; - - public PackageMatchingCache(Supplier<String> pkgSource) { - mPkgSource = pkgSource; - } - - public boolean matches(String pkgCandidate) { - if (pkgCandidate == null) return false; - - if (Objects.equals(pkgCandidate, mCurrentPkg)) { - return true; - } - // Failed on cached value, try updating. - mCurrentPkg = mPkgSource.get(); - return Objects.equals(pkgCandidate, mCurrentPkg); - } - } - public static class Lifecycle extends SystemService { private SliceManagerService mService; diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java index c2b0d1067e38..0ca36e0fc258 100644 --- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java +++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java @@ -72,6 +72,10 @@ public final class TimeZoneDetectorCallbackImpl implements TimeZoneDetectorStrat builder.setConfigureAutoDetectionEnabled(CAPABILITY_POSSESSED); } + // TODO(b/149014708) Replace this with real logic when the settings storage is fully + // implemented. + builder.setConfigureGeoDetectionEnabled(CAPABILITY_NOT_SUPPORTED); + // The ability to make manual time zone suggestions can also be restricted by policy. With // the current logic above, this could lead to a situation where a device hardware does not // support auto detection, the device has been forced into "auto" mode by an admin and the @@ -90,6 +94,7 @@ public final class TimeZoneDetectorCallbackImpl implements TimeZoneDetectorStrat public TimeZoneConfiguration getConfiguration(@UserIdInt int userId) { return new TimeZoneConfiguration.Builder() .setAutoDetectionEnabled(isAutoDetectionEnabled()) + .setGeoDetectionEnabled(isGeoDetectionEnabled()) .build(); } @@ -105,8 +110,11 @@ public final class TimeZoneDetectorCallbackImpl implements TimeZoneDetectorStrat // detection: if we wrote it down then we'd set the default explicitly. That might influence // what happens on later releases that do support auto detection on the same hardware. if (isAutoDetectionSupported()) { - final int value = configuration.isAutoDetectionEnabled() ? 1 : 0; - Settings.Global.putInt(mCr, Settings.Global.AUTO_TIME_ZONE, value); + final int autoEnabledValue = configuration.isAutoDetectionEnabled() ? 1 : 0; + Settings.Global.putInt(mCr, Settings.Global.AUTO_TIME_ZONE, autoEnabledValue); + + final boolean geoTzDetectionEnabledValue = configuration.isGeoDetectionEnabled(); + // TODO(b/149014708) Write this down to user-scoped settings once implemented. } } @@ -126,6 +134,14 @@ public final class TimeZoneDetectorCallbackImpl implements TimeZoneDetectorStrat } @Override + public boolean isGeoDetectionEnabled() { + // TODO(b/149014708) Read this from user-scoped settings once implemented. The user's + // location toggle will act as an override for this setting, i.e. so that the setting will + // return false if the location toggle is disabled. + return false; + } + + @Override public boolean isDeviceTimeZoneInitialized() { // timezone.equals("GMT") will be true and only true if the time zone was // set to a default value by the system server (when starting, system server diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java index 3d9ec6475a8b..fb7a73d12632 100644 --- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java +++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; * The internal (in-process) system server API for the {@link * com.android.server.timezonedetector.TimeZoneDetectorService}. * + * <p>The methods on this class can be called from any thread. * @hide */ public interface TimeZoneDetectorInternal extends Dumpable.Container { @@ -29,7 +30,7 @@ public interface TimeZoneDetectorInternal extends Dumpable.Container { /** * Suggests the current time zone, determined using geolocation, to the detector. The * detector may ignore the signal based on system settings, whether better information is - * available, and so on. + * available, and so on. This method may be implemented asynchronously. */ void suggestGeolocationTimeZone(@NonNull GeolocationTimeZoneSuggestion timeZoneSuggestion); } diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java index 4464f7d136e3..15412a0d14a1 100644 --- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java +++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java @@ -58,6 +58,7 @@ public final class TimeZoneDetectorInternalImpl implements TimeZoneDetectorInter @NonNull GeolocationTimeZoneSuggestion timeZoneSuggestion) { Objects.requireNonNull(timeZoneSuggestion); + // All strategy calls must take place on the mHandler thread. mHandler.post( () -> mTimeZoneDetectorStrategy.suggestGeolocationTimeZone(timeZoneSuggestion)); } diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java index 7467439905eb..d81f949742bd 100644 --- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java +++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java @@ -130,6 +130,10 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub service.handleAutoTimeZoneConfigChanged(); } }); + // TODO(b/149014708) Listen for changes to geolocation time zone detection enabled config. + // This should also include listening to the current user and the current user's location + // toggle since the config is user-scoped and the location toggle overrides the geolocation + // time zone enabled setting. return service; } @@ -280,7 +284,7 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub void handleConfigurationChanged() { // Note: we could trigger an async time zone detection operation here via a call to - // handleAutoTimeZoneDetectionChanged(), but that is triggered in response to the underlying + // handleAutoTimeZoneConfigChanged(), but that is triggered in response to the underlying // setting value changing so it is currently unnecessary. If we get to a point where all // configuration changes are guaranteed to happen in response to an updateConfiguration() // call, then we can remove that path and call it here instead. @@ -288,7 +292,6 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub // Configuration has changed, but each user may have a different view of the configuration. // It's possible that this will cause unnecessary notifications but that shouldn't be a // problem. - synchronized (mConfigurationListeners) { final int userCount = mConfigurationListeners.size(); for (int userIndex = 0; userIndex < userCount; userIndex++) { diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java index f947a6554412..c5b7e39f4fef 100644 --- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java +++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java @@ -30,9 +30,9 @@ import android.util.IndentingPrintWriter; * <p>The strategy uses suggestions to decide whether to modify the device's time zone setting * and what to set it to. * - * <p>Most calls will be handled by a single thread but that is not true for all calls. For example - * {@link #dump(IndentingPrintWriter, String[])}) may be called on a different thread so - * implementations mustvhandle thread safety. + * <p>Most calls will be handled by a single thread, but that is not true for all calls. For example + * {@link #dump(IndentingPrintWriter, String[])}) may be called on a different thread concurrently + * with other operations so implementations must still handle thread safety. * * @hide */ diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java index 9c36c3921e3e..d1369a289428 100644 --- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java +++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java @@ -23,6 +23,7 @@ import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_S import static android.app.timezonedetector.TimeZoneCapabilities.CAPABILITY_NOT_APPLICABLE; import static android.app.timezonedetector.TimeZoneCapabilities.CAPABILITY_POSSESSED; import static android.app.timezonedetector.TimeZoneConfiguration.PROPERTY_AUTO_DETECTION_ENABLED; +import static android.app.timezonedetector.TimeZoneConfiguration.PROPERTY_GEO_DETECTION_ENABLED; import android.annotation.NonNull; import android.annotation.Nullable; @@ -98,6 +99,12 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat boolean isAutoDetectionEnabled(); /** + * Returns whether geolocation can be used for time zone detection when {@link + * #isAutoDetectionEnabled()} returns {@code true}. + */ + boolean isGeoDetectionEnabled(); + + /** * Returns true if the device has had an explicit time zone set. */ boolean isDeviceTimeZoneInitialized(); @@ -200,7 +207,15 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat */ @GuardedBy("this") private ArrayMapWithHistory<Integer, QualifiedTelephonyTimeZoneSuggestion> - mSuggestionBySlotIndex = new ArrayMapWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE); + mTelephonySuggestionsBySlotIndex = + new ArrayMapWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE); + + /** + * The latest geolocation suggestion received. + */ + @GuardedBy("this") + private ReferenceWithHistory<GeolocationTimeZoneSuggestion> mLatestGeoLocationSuggestion = + new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE); @GuardedBy("this") private final List<Dumpable> mDumpables = new ArrayList<>(); @@ -284,17 +299,26 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat private static boolean containsAutoTimeDetectionProperties( @NonNull TimeZoneConfiguration configuration) { - return configuration.hasProperty(PROPERTY_AUTO_DETECTION_ENABLED); + return configuration.hasProperty(PROPERTY_AUTO_DETECTION_ENABLED) + || configuration.hasProperty(PROPERTY_GEO_DETECTION_ENABLED); } @Override public synchronized void suggestGeolocationTimeZone( @NonNull GeolocationTimeZoneSuggestion suggestion) { + if (DBG) { + Slog.d(LOG_TAG, "Geolocation suggestion received. newSuggestion=" + suggestion); + } + Objects.requireNonNull(suggestion); + mLatestGeoLocationSuggestion.set(suggestion); - // TODO Implement this. - throw new UnsupportedOperationException( - "Geo-location time zone detection is not currently implemented"); + // Now perform auto time zone detection. The new suggestion may be used to modify the time + // zone setting. + if (mCallback.isGeoDetectionEnabled()) { + String reason = "New geolocation time zone suggested. suggestion=" + suggestion; + doAutoTimeZoneDetection(reason); + } } @Override @@ -332,12 +356,14 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat new QualifiedTelephonyTimeZoneSuggestion(suggestion, score); // Store the suggestion against the correct slotIndex. - mSuggestionBySlotIndex.put(suggestion.getSlotIndex(), scoredSuggestion); + mTelephonySuggestionsBySlotIndex.put(suggestion.getSlotIndex(), scoredSuggestion); // Now perform auto time zone detection. The new suggestion may be used to modify the time // zone setting. - String reason = "New telephony time suggested. suggestion=" + suggestion; - doAutoTimeZoneDetection(reason); + if (!mCallback.isGeoDetectionEnabled()) { + String reason = "New telephony time zone suggested. suggestion=" + suggestion; + doAutoTimeZoneDetection(reason); + } } private static int scoreTelephonySuggestion(@NonNull TelephonyTimeZoneSuggestion suggestion) { @@ -363,9 +389,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat } /** - * Finds the best available time zone suggestion from all slotIndexes. If it is high-enough - * quality and automatic time zone detection is enabled then it will be set on the device. The - * outcome can be that this strategy becomes / remains un-opinionated and nothing is set. + * Performs automatic time zone detection. */ @GuardedBy("this") private void doAutoTimeZoneDetection(@NonNull String detectionReason) { @@ -374,6 +398,62 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat return; } + // Use the right suggestions based on the current configuration. This check is potentially + // race-prone until this value is set via a call to TimeZoneDetectorStrategy. + if (mCallback.isGeoDetectionEnabled()) { + doGeolocationTimeZoneDetection(detectionReason); + } else { + doTelephonyTimeZoneDetection(detectionReason); + } + } + + /** + * Detects the time zone using the latest available geolocation time zone suggestion, if one is + * available. The outcome can be that this strategy becomes / remains un-opinionated and nothing + * is set. + */ + @GuardedBy("this") + private void doGeolocationTimeZoneDetection(@NonNull String detectionReason) { + GeolocationTimeZoneSuggestion latestGeolocationSuggestion = + mLatestGeoLocationSuggestion.get(); + if (latestGeolocationSuggestion == null) { + return; + } + + List<String> zoneIds = latestGeolocationSuggestion.getZoneIds(); + if (zoneIds == null || zoneIds.isEmpty()) { + // This means the client has become uncertain about the time zone or it is certain there + // is no known zone. In either case we must leave the existing time zone setting as it + // is. + return; + } + + // GeolocationTimeZoneSuggestion has no measure of quality. We assume all suggestions are + // reliable. + String zoneId; + + // Introduce bias towards the device's current zone when there are multiple zone suggested. + String deviceTimeZone = mCallback.getDeviceTimeZone(); + if (zoneIds.contains(deviceTimeZone)) { + if (DBG) { + Slog.d(LOG_TAG, + "Geo tz suggestion contains current device time zone. Applying bias."); + } + zoneId = deviceTimeZone; + } else { + zoneId = zoneIds.get(0); + } + setDeviceTimeZoneIfRequired(zoneId, detectionReason); + } + + /** + * Detects the time zone using the latest available telephony time zone suggestions. + * Finds the best available time zone suggestion from all slotIndexes. If it is high-enough + * quality and automatic time zone detection is enabled then it will be set on the device. The + * outcome can be that this strategy becomes / remains un-opinionated and nothing is set. + */ + @GuardedBy("this") + private void doTelephonyTimeZoneDetection(@NonNull String detectionReason) { QualifiedTelephonyTimeZoneSuggestion bestTelephonySuggestion = findBestTelephonySuggestion(); @@ -468,9 +548,9 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat // slotIndex and find the best. Note that we deliberately do not look at age: the caller can // rate-limit so age is not a strong indicator of confidence. Instead, the callers are // expected to withdraw suggestions they no longer have confidence in. - for (int i = 0; i < mSuggestionBySlotIndex.size(); i++) { + for (int i = 0; i < mTelephonySuggestionsBySlotIndex.size(); i++) { QualifiedTelephonyTimeZoneSuggestion candidateSuggestion = - mSuggestionBySlotIndex.valueAt(i); + mTelephonySuggestionsBySlotIndex.valueAt(i); if (candidateSuggestion == null) { // Unexpected continue; @@ -505,14 +585,10 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat @Override public synchronized void handleAutoTimeZoneConfigChanged() { if (DBG) { - Slog.d(LOG_TAG, "handleTimeZoneDetectionChange() called"); - } - if (mCallback.isAutoDetectionEnabled()) { - // When the user enabled time zone detection, run the time zone detection and change the - // device time zone if possible. - String reason = "Auto time zone detection setting enabled."; - doAutoTimeZoneDetection(reason); + Slog.d(LOG_TAG, "handleAutoTimeZoneConfigChanged()"); } + + doAutoTimeZoneDetection("handleAutoTimeZoneConfigChanged()"); } @Override @@ -532,15 +608,21 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat ipw.println("mCallback.isDeviceTimeZoneInitialized()=" + mCallback.isDeviceTimeZoneInitialized()); ipw.println("mCallback.getDeviceTimeZone()=" + mCallback.getDeviceTimeZone()); + ipw.println("mCallback.isGeoDetectionEnabled()=" + mCallback.isGeoDetectionEnabled()); ipw.println("Time zone change log:"); ipw.increaseIndent(); // level 2 mTimeZoneChangesLog.dump(ipw); ipw.decreaseIndent(); // level 2 + ipw.println("Geolocation suggestion history:"); + ipw.increaseIndent(); // level 2 + mLatestGeoLocationSuggestion.dump(ipw); + ipw.decreaseIndent(); // level 2 + ipw.println("Telephony suggestion history:"); ipw.increaseIndent(); // level 2 - mSuggestionBySlotIndex.dump(ipw); + mTelephonySuggestionsBySlotIndex.dump(ipw); ipw.decreaseIndent(); // level 2 ipw.decreaseIndent(); // level 1 @@ -555,7 +637,15 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat @VisibleForTesting public synchronized QualifiedTelephonyTimeZoneSuggestion getLatestTelephonySuggestion( int slotIndex) { - return mSuggestionBySlotIndex.get(slotIndex); + return mTelephonySuggestionsBySlotIndex.get(slotIndex); + } + + /** + * A method used to inspect strategy state during tests. Not intended for general use. + */ + @VisibleForTesting + public GeolocationTimeZoneSuggestion getLatestGeolocationSuggestion() { + return mLatestGeoLocationSuggestion.get(); } /** diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 2f695c6fd3f1..202a3dcf46dc 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -3070,7 +3070,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub mLockWallpaperMap.put(userId, wallpaper); ensureSaneWallpaperData(wallpaper); } else { - // sanity fallback: we're in bad shape, but establishing a known + // rationality fallback: we're in bad shape, but establishing a known // valid system+lock WallpaperData will keep us from dying. Slog.wtf(TAG, "Didn't find wallpaper in non-lock case!"); wallpaper = new WallpaperData(userId, getWallpaperDir(userId), diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index e573d362fef4..5b8078729eee 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -107,6 +107,12 @@ import static android.view.WindowManager.TRANSIT_TASK_CLOSE; import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND; import static android.view.WindowManager.TRANSIT_UNSET; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import static com.android.server.wm.ActivityRecordProto.ALL_DRAWN; @@ -172,12 +178,6 @@ import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchi import static com.android.server.wm.IdentifierProto.HASH_CODE; import static com.android.server.wm.IdentifierProto.TITLE; import static com.android.server.wm.IdentifierProto.USER_ID; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; import static com.android.server.wm.Task.ActivityState.DESTROYED; @@ -294,6 +294,7 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.ResolverActivity; import com.android.internal.content.ReferrerIntent; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.ToBooleanFunction; import com.android.internal.util.XmlUtils; import com.android.internal.util.function.pooled.PooledConsumer; @@ -305,7 +306,6 @@ import com.android.server.am.AppTimeTracker; import com.android.server.am.PendingIntentRecord; import com.android.server.display.color.ColorDisplayService; import com.android.server.policy.WindowManagerPolicy; -import com.android.server.protolog.common.ProtoLog; import com.android.server.uri.NeededUriGrants; import com.android.server.uri.UriPermissionOwner; import com.android.server.wm.ActivityMetricsLogger.TransitionInfoSnapshot; diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index 11a468be8f9f..f76108f332d1 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -67,10 +67,10 @@ import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpe import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation; import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation; import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM; import static com.android.server.wm.AppTransitionProto.APP_TRANSITION_STATE; import static com.android.server.wm.AppTransitionProto.LAST_USED_APP_TRANSITION; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -127,11 +127,11 @@ import android.view.animation.TranslateAnimation; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.DumpUtils.Dump; import com.android.internal.util.function.pooled.PooledLambda; import com.android.internal.util.function.pooled.PooledPredicate; import com.android.server.AttributeCache; -import com.android.server.protolog.common.ProtoLog; import com.android.server.wm.animation.ClipRectLRAnimation; import com.android.server.wm.animation.ClipRectTBAnimation; import com.android.server.wm.animation.CurvedTranslateAnimation; diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index 5720e9b7f193..57d51c51c12b 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -41,14 +41,14 @@ import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE; import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN; import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SNAPSHOT; import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SPLASH_SCREEN; import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN; import static com.android.server.wm.AppTransition.isKeyguardGoingAwayTransit; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; @@ -69,7 +69,7 @@ import android.view.WindowManager.TransitionType; import android.view.animation.Animation; import com.android.internal.annotations.VisibleForTesting; -import com.android.server.protolog.common.ProtoLog; +import com.android.internal.protolog.common.ProtoLog; import java.util.ArrayList; import java.util.LinkedList; diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java index f563e57b363e..0b2c851c4366 100644 --- a/services/core/java/com/android/server/wm/BlackFrame.java +++ b/services/core/java/com/android/server/wm/BlackFrame.java @@ -16,13 +16,13 @@ package com.android.server.wm; -import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; +import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; import android.graphics.Rect; import android.view.Surface.OutOfResourcesException; import android.view.SurfaceControl; -import com.android.server.protolog.common.ProtoLog; +import com.android.internal.protolog.common.ProtoLog; import java.io.PrintWriter; import java.util.function.Supplier; diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java index 6ffb48282017..8bd42f03ff86 100644 --- a/services/core/java/com/android/server/wm/DisplayArea.java +++ b/services/core/java/com/android/server/wm/DisplayArea.java @@ -24,11 +24,11 @@ import static android.view.WindowManagerPolicyConstants.APPLICATION_LAYER; import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED; import static android.window.DisplayAreaOrganizer.FEATURE_WINDOW_TOKENS; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.internal.util.Preconditions.checkState; import static com.android.server.wm.DisplayAreaProto.IS_TASK_DISPLAY_AREA; import static com.android.server.wm.DisplayAreaProto.NAME; import static com.android.server.wm.DisplayAreaProto.WINDOW_CONTAINER; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.wm.WindowContainerChildProto.DISPLAY_AREA; import android.annotation.Nullable; @@ -38,8 +38,8 @@ import android.util.proto.ProtoOutputStream; import android.window.DisplayAreaInfo; import android.window.IDisplayAreaOrganizer; +import com.android.internal.protolog.common.ProtoLog; import com.android.server.policy.WindowManagerPolicy; -import com.android.server.protolog.common.ProtoLog; import java.util.Comparator; import java.util.function.BiFunction; diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index fc170538994c..ba5a38290349 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -74,6 +74,14 @@ import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT; import static android.window.DisplayAreaOrganizer.FEATURE_ROOT; import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON; +import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; @@ -94,14 +102,6 @@ import static com.android.server.wm.DisplayContentProto.ROOT_DISPLAY_AREA; import static com.android.server.wm.DisplayContentProto.ROTATION; import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION; import static com.android.server.wm.DisplayContentProto.SINGLE_TASK_INSTANCE; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_BOOT; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON; -import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.server.wm.Task.ActivityState.RESUMED; import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; @@ -203,6 +203,7 @@ import android.view.WindowManagerPolicyConstants.PointerEventListener; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.ToBooleanFunction; import com.android.internal.util.function.TriConsumer; import com.android.internal.util.function.pooled.PooledConsumer; @@ -211,7 +212,6 @@ import com.android.internal.util.function.pooled.PooledLambda; import com.android.internal.util.function.pooled.PooledPredicate; import com.android.server.inputmethod.InputMethodManagerInternal; import com.android.server.policy.WindowManagerPolicy; -import com.android.server.protolog.common.ProtoLog; import com.android.server.wm.utils.DisplayRotationUtil; import com.android.server.wm.utils.RotationCache; import com.android.server.wm.utils.WmDisplayCutout; @@ -4063,9 +4063,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM, "Taking screenshot while rotating"); // Send invalid rect and no width and height since it will screenshot the entire display. - Rect frame = new Rect(0, 0, -1, -1); - final Bitmap bitmap = SurfaceControl.screenshot(frame, 0, 0, inRotation, - mDisplay.getRotation()); + final IBinder displayToken = SurfaceControl.getInternalDisplayToken(); + final SurfaceControl.DisplayCaptureArgs captureArgs = + new SurfaceControl.DisplayCaptureArgs.Builder(displayToken) + .setUseIdentityTransform(inRotation) + .build(); + final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer = + SurfaceControl.captureDisplay(captureArgs); + final Bitmap bitmap = screenshotBuffer == null ? null : screenshotBuffer.asBitmap(); if (bitmap == null) { Slog.w(TAG_WM, "Failed to take screenshot"); return null; diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 4f6f75d924c4..2e03cb80b189 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -112,6 +112,7 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM; import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT; import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON; import static com.android.server.policy.PhoneWindowManager.TOAST_WINDOW_TIMEOUT; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER; @@ -120,7 +121,6 @@ import static com.android.server.policy.WindowManagerPolicy.TRANSIT_HIDE; import static com.android.server.policy.WindowManagerPolicy.TRANSIT_PREVIEW_DONE; import static com.android.server.policy.WindowManagerPolicy.TRANSIT_SHOW; import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -187,6 +187,7 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.GestureNavigationSettingsObserver; import com.android.internal.policy.ScreenDecorationsUtils; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.ScreenshotHelper; import com.android.internal.util.function.TriConsumer; import com.android.internal.view.AppearanceRegion; @@ -199,7 +200,6 @@ import com.android.server.policy.WindowManagerPolicy.NavigationBarPosition; import com.android.server.policy.WindowManagerPolicy.ScreenOnListener; import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs; import com.android.server.policy.WindowOrientationListener; -import com.android.server.protolog.common.ProtoLog; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.wallpaper.WallpaperManagerInternal; import com.android.server.wm.utils.InsetUtils; diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index c63128c15e8d..0206787ef226 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -22,8 +22,8 @@ import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -58,12 +58,12 @@ import android.window.WindowContainerTransaction; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.LocalServices; import com.android.server.UiThread; import com.android.server.policy.WindowManagerPolicy; import com.android.server.policy.WindowOrientationListener; -import com.android.server.protolog.common.ProtoLog; import com.android.server.statusbar.StatusBarManagerInternal; import java.io.PrintWriter; diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index 22dd1d332345..133b11116460 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -18,11 +18,11 @@ package com.android.server.wm; import static android.os.IInputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; +import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.server.wm.DragDropController.MSG_ANIMATION_END; import static com.android.server.wm.DragDropController.MSG_DRAG_END_TIMEOUT; import static com.android.server.wm.DragDropController.MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; -import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG; import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -58,9 +58,9 @@ import android.view.WindowManager; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.view.IDragAndDropPermissions; import com.android.server.LocalServices; -import com.android.server.protolog.common.ProtoLog; import java.util.ArrayList; diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java index e7fbc334306e..86e2698302aa 100644 --- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java @@ -16,13 +16,13 @@ package com.android.server.wm; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME; import android.view.InsetsSource; import android.view.WindowInsets; import com.android.internal.annotations.VisibleForTesting; -import com.android.server.protolog.common.ProtoLog; +import com.android.internal.protolog.common.ProtoLog; import java.io.PrintWriter; diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 791f47128be0..0fe9735c9e46 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -41,7 +41,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -60,8 +60,8 @@ import android.view.InputEventReceiver; import android.view.InputWindowHandle; import android.view.SurfaceControl; +import com.android.internal.protolog.common.ProtoLog; import com.android.server.policy.WindowManagerPolicy; -import com.android.server.protolog.common.ProtoLog; import java.io.PrintWriter; import java.util.Set; diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index f64149cee8c7..d1eb79556d1d 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -24,7 +24,7 @@ import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME; import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE; import static android.view.ViewRootImpl.sNewInsetsMode; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_INSETS_CONTROL; import static com.android.server.wm.WindowManagerService.H.LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED; @@ -40,8 +40,8 @@ import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.function.TriConsumer; -import com.android.server.protolog.common.ProtoLog; import com.android.server.wm.SurfaceAnimator.AnimationType; import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index 33dde3221804..ab1074ee2821 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -30,7 +30,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME; import android.annotation.NonNull; import android.annotation.Nullable; @@ -45,8 +45,8 @@ import android.view.InsetsState; import android.view.InsetsState.InternalInsetsType; import android.view.WindowManager; +import com.android.internal.protolog.common.ProtoLog; import com.android.server.inputmethod.InputMethodManagerInternal; -import com.android.server.protolog.common.ProtoLog; import java.io.PrintWriter; import java.util.ArrayList; diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java index d7b43bc5537d..6c416830b59e 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimation.java +++ b/services/core/java/com/android/server/wm/RecentsAnimation.java @@ -25,8 +25,8 @@ import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.WindowManager.TRANSIT_NONE; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS; import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS; import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE; import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION; import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_TOP; @@ -41,9 +41,9 @@ import android.os.Trace; import android.util.Slog; import android.view.IRecentsAnimationRunner; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.function.pooled.PooledLambda; import com.android.internal.util.function.pooled.PooledPredicate; -import com.android.server.protolog.common.ProtoLog; import com.android.server.wm.ActivityMetricsLogger.LaunchingState; import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks; diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 6b3a5d6bf18c..143fbb0fe48b 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -23,10 +23,10 @@ import static android.view.RemoteAnimationTarget.MODE_OPENING; import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM; import static com.android.server.wm.AnimationAdapterProto.REMOTE; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS; import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS; import static com.android.server.wm.WindowManagerInternal.AppTransitionListener; @@ -56,12 +56,12 @@ import android.view.SurfaceControl.Transaction; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.inputmethod.SoftInputShowHideReason; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.function.pooled.PooledConsumer; import com.android.internal.util.function.pooled.PooledFunction; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.LocalServices; import com.android.server.inputmethod.InputMethodManagerInternal; -import com.android.server.protolog.common.ProtoLog; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.wm.SurfaceAnimator.AnimationType; import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java index c255a18190f7..e7461e7d5517 100644 --- a/services/core/java/com/android/server/wm/RemoteAnimationController.java +++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java @@ -16,8 +16,8 @@ package com.android.server.wm; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS; import static com.android.server.wm.AnimationAdapterProto.REMOTE; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS; import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -37,9 +37,9 @@ import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; +import com.android.internal.protolog.ProtoLogImpl; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.FastPrintWriter; -import com.android.server.protolog.ProtoLogImpl; -import com.android.server.protolog.common.ProtoLog; import com.android.server.wm.SurfaceAnimator.AnimationType; import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 1cb483c1d1a0..b3a3ed7eeba4 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -41,6 +41,11 @@ import static android.view.WindowManager.TRANSIT_NONE; import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY; import static android.view.WindowManager.TRANSIT_TASK_TO_BACK; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; +import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; +import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.server.policy.PhoneWindowManager.SYSTEM_DIALOG_REASON_ASSIST; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; @@ -59,11 +64,6 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATE import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS; import static com.android.server.wm.ActivityTaskManagerService.ANIMATE; import static com.android.server.wm.ActivityTaskManagerService.TAG_SWITCH; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; -import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; -import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE; import static com.android.server.wm.RootWindowContainerProto.IS_HOME_RECENTS_COMPONENT; import static com.android.server.wm.RootWindowContainerProto.KEYGUARD_CONTROLLER; @@ -146,6 +146,7 @@ import android.window.WindowContainerToken; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.ResolverActivity; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.function.pooled.PooledConsumer; import com.android.internal.util.function.pooled.PooledFunction; import com.android.internal.util.function.pooled.PooledLambda; @@ -155,7 +156,6 @@ import com.android.server.am.ActivityManagerService; import com.android.server.am.AppTimeTracker; import com.android.server.am.UserState; import com.android.server.policy.WindowManagerPolicy; -import com.android.server.protolog.common.ProtoLog; import java.io.FileDescriptor; import java.io.PrintWriter; diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index d7b8fb00d05c..3c8036d4e3b6 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -18,9 +18,9 @@ package com.android.server.wm; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; +import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; import static com.android.server.wm.AnimationSpecProto.ROTATE; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; -import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; import static com.android.server.wm.RotationAnimationSpecProto.DURATION_MS; import static com.android.server.wm.RotationAnimationSpecProto.END_LUMA; import static com.android.server.wm.RotationAnimationSpecProto.START_LUMA; @@ -50,7 +50,7 @@ import android.view.animation.AnimationUtils; import android.view.animation.Transformation; import com.android.internal.R; -import com.android.server.protolog.common.ProtoLog; +import com.android.internal.protolog.common.ProtoLog; import com.android.server.wm.SurfaceAnimator.AnimationType; import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; import com.android.server.wm.utils.RotationAnimationUtils; diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 86cbf3e3afe1..3b32a9d76258 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -24,7 +24,7 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType; -import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; +import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -58,7 +58,7 @@ import android.view.SurfaceSession; import android.view.WindowManager; import com.android.internal.os.logging.MetricsLoggerWrapper; -import com.android.server.protolog.common.ProtoLog; +import com.android.internal.protolog.common.ProtoLog; import com.android.server.wm.WindowManagerService.H; import java.io.PrintWriter; diff --git a/services/core/java/com/android/server/wm/SurfaceFreezer.java b/services/core/java/com/android/server/wm/SurfaceFreezer.java index 1c9743041923..d9365c5d0666 100644 --- a/services/core/java/com/android/server/wm/SurfaceFreezer.java +++ b/services/core/java/com/android/server/wm/SurfaceFreezer.java @@ -16,7 +16,7 @@ package com.android.server.wm; -import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; +import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_SCREEN_ROTATION; @@ -28,7 +28,7 @@ import android.hardware.HardwareBuffer; import android.view.Surface; import android.view.SurfaceControl; -import com.android.server.protolog.common.ProtoLog; +import com.android.internal.protolog.common.ProtoLog; import java.util.function.Supplier; diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index be0815b06051..ec7b1eed7f91 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -78,6 +78,8 @@ import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT; import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP; import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS; import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN; import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME; import static com.android.server.wm.ActivityStackSupervisor.ON_TOP; @@ -116,8 +118,6 @@ import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_ import static com.android.server.wm.IdentifierProto.HASH_CODE; import static com.android.server.wm.IdentifierProto.TITLE; import static com.android.server.wm.IdentifierProto.USER_ID; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS; import static com.android.server.wm.Task.ActivityState.PAUSED; import static com.android.server.wm.Task.ActivityState.PAUSING; import static com.android.server.wm.Task.ActivityState.RESUMED; @@ -210,6 +210,7 @@ import android.window.ITaskOrganizer; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IVoiceInteractor; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.XmlUtils; import com.android.internal.util.function.pooled.PooledConsumer; import com.android.internal.util.function.pooled.PooledFunction; @@ -218,7 +219,6 @@ import com.android.internal.util.function.pooled.PooledPredicate; import com.android.server.Watchdog; import com.android.server.am.ActivityManagerService; import com.android.server.am.AppTimeTracker; -import com.android.server.protolog.common.ProtoLog; import com.android.server.uri.NeededUriGrants; import org.xmlpull.v1.XmlPullParser; @@ -7056,17 +7056,21 @@ class Task extends WindowContainer<WindowContainer> { /** * Reset local parameters because an app's activity died. * @param app The app of the activity that died. + * @return {@code true} if the process of the pausing activity is died. */ - void handleAppDied(WindowProcessController app) { + boolean handleAppDied(WindowProcessController app) { + boolean isPausingDied = false; if (mPausingActivity != null && mPausingActivity.app == app) { if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE, "App died while pausing: " + mPausingActivity); mPausingActivity = null; + isPausingDied = true; } if (mLastPausedActivity != null && mLastPausedActivity.app == app) { mLastPausedActivity = null; mLastNoHistoryActivity = null; } + return isPausingDied; } boolean dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient, diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index a847744247c7..32511108836e 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -32,13 +32,13 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS; import static com.android.server.wm.ActivityTaskManagerService.TAG_STACK; import static com.android.server.wm.DisplayContent.alwaysCreateStack; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.wm.RootWindowContainer.TAG_STATES; import static com.android.server.wm.Task.ActivityState.RESUMED; import static com.android.server.wm.Task.STACK_VISIBILITY_VISIBLE; @@ -58,10 +58,10 @@ import android.view.SurfaceControl; import android.window.WindowContainerTransaction; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.ToBooleanFunction; import com.android.internal.util.function.pooled.PooledLambda; import com.android.internal.util.function.pooled.PooledPredicate; -import com.android.server.protolog.common.ProtoLog; import java.io.PrintWriter; import java.util.ArrayList; diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java index 3fbc0373e1a9..a66cd846e8be 100644 --- a/services/core/java/com/android/server/wm/TaskPositioner.java +++ b/services/core/java/com/android/server/wm/TaskPositioner.java @@ -26,8 +26,8 @@ import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_LEFT; import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_NONE; import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_RIGHT; import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_TOP; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -59,7 +59,7 @@ import android.view.WindowManager; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.TaskResizingAlgorithm; import com.android.internal.policy.TaskResizingAlgorithm.CtrlType; -import com.android.server.protolog.common.ProtoLog; +import com.android.internal.protolog.common.ProtoLog; class TaskPositioner implements IBinder.DeathRecipient { private static final boolean DEBUG_ORIENTATION_VIOLATIONS = false; diff --git a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java index 1103bf19b3bf..3def0911bd76 100644 --- a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java +++ b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java @@ -15,14 +15,14 @@ */ package com.android.server.wm; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS; import android.hardware.HardwareBuffer; import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceSession; -import com.android.server.protolog.common.ProtoLog; +import com.android.internal.protolog.common.ProtoLog; import java.util.function.Function; diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java index 9b18ac8f7702..e9ada6be7e7b 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java @@ -41,7 +41,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES; import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES; import static com.android.internal.policy.DecorView.getNavigationBarRect; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; import static com.android.server.wm.TaskSnapshotController.getSystemBarInsets; import static com.android.server.wm.TaskSnapshotController.mergeInsetsSources; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -83,9 +83,9 @@ import android.view.WindowManagerGlobal; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.DecorView; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.view.BaseIWindow; import com.android.server.policy.WindowManagerPolicy.StartingSurface; -import com.android.server.protolog.common.ProtoLog; /** * This class represents a starting window that shows a snapshot. diff --git a/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java b/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java index f46701536cf8..38bff9ed3c31 100644 --- a/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java +++ b/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java @@ -15,8 +15,8 @@ */ package com.android.server.wm; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS; import static com.android.server.wm.AnimationAdapterProto.REMOTE; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS; import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; @@ -26,7 +26,7 @@ import android.util.proto.ProtoOutputStream; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; -import com.android.server.protolog.common.ProtoLog; +import com.android.internal.protolog.common.ProtoLog; import com.android.server.wm.SurfaceAnimator.AnimationType; import java.io.PrintWriter; diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 6377a2169b34..5c6266a2f8c4 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -16,7 +16,7 @@ package com.android.server.wm; -import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; +import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS; @@ -36,8 +36,8 @@ import android.util.TimeUtils; import android.view.Choreographer; import android.view.SurfaceControl; +import com.android.internal.protolog.common.ProtoLog; import com.android.server.policy.WindowManagerPolicy; -import com.android.server.protolog.common.ProtoLog; import java.io.PrintWriter; import java.util.ArrayList; diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index e24d185557e8..8a5e70f2e353 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -28,14 +28,14 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.os.UserHandle.USER_NULL; import static android.view.SurfaceControl.Transaction; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import static com.android.server.wm.AppTransition.MAX_APP_TRANSITION_DURATION; import static com.android.server.wm.IdentifierProto.HASH_CODE; import static com.android.server.wm.IdentifierProto.TITLE; import static com.android.server.wm.IdentifierProto.USER_ID; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; @@ -82,8 +82,8 @@ import android.window.IWindowContainerToken; import android.window.WindowContainerToken; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.ToBooleanFunction; -import com.android.server.protolog.common.ProtoLog; import com.android.server.wm.SurfaceAnimator.Animatable; import com.android.server.wm.SurfaceAnimator.AnimationType; import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; diff --git a/services/core/java/com/android/server/wm/WindowContainerThumbnail.java b/services/core/java/com/android/server/wm/WindowContainerThumbnail.java index b75f886520e6..b9f67a590c2a 100644 --- a/services/core/java/com/android/server/wm/WindowContainerThumbnail.java +++ b/services/core/java/com/android/server/wm/WindowContainerThumbnail.java @@ -19,7 +19,7 @@ package com.android.server.wm; import static android.view.SurfaceControl.METADATA_OWNER_UID; import static android.view.SurfaceControl.METADATA_WINDOW_TYPE; -import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; +import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS; import static com.android.server.wm.WindowContainerThumbnailProto.HEIGHT; import static com.android.server.wm.WindowContainerThumbnailProto.SURFACE_ANIMATOR; @@ -39,7 +39,7 @@ import android.view.SurfaceControl.Builder; import android.view.SurfaceControl.Transaction; import android.view.animation.Animation; -import com.android.server.protolog.common.ProtoLog; +import com.android.internal.protolog.common.ProtoLog; import com.android.server.wm.SurfaceAnimator.Animatable; import com.android.server.wm.SurfaceAnimator.AnimationType; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 0b1d6bc0adfd..b33a8e9ef5df 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -84,22 +84,22 @@ import static android.view.WindowManagerGlobal.RELAYOUT_RES_BLAST_SYNC; import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED; import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT; +import static com.android.internal.protolog.ProtoLogGroup.WM_ERROR; +import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN; import static com.android.server.LockGuard.INDEX_WINDOW; import static com.android.server.LockGuard.installLock; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_BOOT; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT; -import static com.android.server.wm.ProtoLogGroup.WM_ERROR; -import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; @@ -265,6 +265,8 @@ import com.android.internal.os.IResultReceiver; import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.policy.IShortcutService; import com.android.internal.policy.KeyInterceptionInfo; +import com.android.internal.protolog.ProtoLogImpl; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.DumpUtils; import com.android.internal.util.FastPrintWriter; import com.android.internal.util.LatencyTracker; @@ -281,8 +283,6 @@ import com.android.server.input.InputManagerService; import com.android.server.policy.WindowManagerPolicy; import com.android.server.policy.WindowManagerPolicy.ScreenOffListener; import com.android.server.power.ShutdownThread; -import com.android.server.protolog.ProtoLogImpl; -import com.android.server.protolog.common.ProtoLog; import com.android.server.utils.PriorityDump; import com.android.server.wm.utils.DeviceConfigInterface; diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java index bdecb8d99752..271d2b1a002f 100644 --- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java +++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java @@ -31,7 +31,7 @@ import android.view.Surface; import android.view.ViewDebug; import com.android.internal.os.ByteTransferPipe; -import com.android.server.protolog.ProtoLogImpl; +import com.android.internal.protolog.ProtoLogImpl; import java.io.IOException; import java.io.PrintWriter; diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index 70c30c9180d7..ab6e35b452a0 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -1201,7 +1201,10 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio final Task rootTask = r.getRootTask(); if (rootTask != null) { - rootTask.handleAppDied(this); + // There may be a pausing activity that hasn't shown any window and was requested + // to be hidden. But pausing is also a visible state, it should be regarded as + // visible, so the caller can know the next activity should be resumed. + hasVisibleActivities |= rootTask.handleAppDied(this); } r.handleAppDied(); } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index d9557fa6b37a..ebbd74aa7d1e 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -101,6 +101,14 @@ import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFO import static android.view.WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME; import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RESIZE; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; import static com.android.server.am.ActivityManagerService.MY_PID; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER; @@ -116,14 +124,6 @@ import static com.android.server.wm.IdentifierProto.USER_ID; import static com.android.server.wm.MoveAnimationSpecProto.DURATION_MS; import static com.android.server.wm.MoveAnimationSpecProto.FROM; import static com.android.server.wm.MoveAnimationSpecProto.TO; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RESIZE; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; @@ -236,10 +236,10 @@ import android.view.animation.Interpolator; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.KeyInterceptionInfo; +import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.ToBooleanFunction; import com.android.server.policy.WindowManagerPolicy; -import com.android.server.protolog.common.ProtoLog; import com.android.server.wm.LocalAnimationAdapter.AnimationSpec; import com.android.server.wm.SurfaceAnimator.AnimationType; import com.android.server.wm.utils.WmDisplayCutout; diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index d0101adaabad..16edb55939a3 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -31,13 +31,13 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static android.view.WindowManager.TRANSIT_NONE; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_DRAW; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; +import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; +import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_DRAW; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; -import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; -import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; @@ -76,8 +76,8 @@ import android.view.WindowManager.LayoutParams; import android.view.animation.Animation; import android.view.animation.AnimationUtils; +import com.android.internal.protolog.common.ProtoLog; import com.android.server.policy.WindowManagerPolicy; -import com.android.server.protolog.common.ProtoLog; import java.io.PrintWriter; diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index b89cdd32e132..9b40822c8ab5 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -21,8 +21,8 @@ import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW; import static android.view.SurfaceControl.METADATA_OWNER_UID; import static android.view.SurfaceControl.METADATA_WINDOW_TYPE; -import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; -import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS; +import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; +import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -40,7 +40,7 @@ import android.view.SurfaceControl; import android.view.WindowContentFrameStats; import android.view.WindowManager; -import com.android.server.protolog.common.ProtoLog; +import com.android.internal.protolog.common.ProtoLog; import java.io.PrintWriter; diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 2c1bb3ec51eb..f7cd37fb6748 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -23,10 +23,10 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS; -import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT; -import static com.android.server.wm.ProtoLogGroup.WM_ERROR; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT; +import static com.android.internal.protolog.ProtoLogGroup.WM_ERROR; import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; @@ -59,8 +59,8 @@ import android.view.SurfaceControl; import android.view.WindowManager; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.protolog.common.ProtoLog; import com.android.server.policy.WindowManagerPolicy; -import com.android.server.protolog.common.ProtoLog; import java.io.PrintWriter; import java.util.ArrayList; diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java index ba3dc607f6cc..e8b8bfce21a3 100644 --- a/services/core/java/com/android/server/wm/WindowTracing.java +++ b/services/core/java/com/android/server/wm/WindowTracing.java @@ -34,7 +34,7 @@ import android.util.Log; import android.util.proto.ProtoOutputStream; import android.view.Choreographer; -import com.android.server.protolog.ProtoLogImpl; +import com.android.internal.protolog.ProtoLogImpl; import com.android.internal.util.TraceBuffer; import java.io.File; diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp index b6633ced771b..529fb8838aa1 100644 --- a/services/core/jni/com_android_server_VibratorService.cpp +++ b/services/core/jni/com_android_server_VibratorService.cpp @@ -17,9 +17,7 @@ #define LOG_TAG "VibratorService" #include <android/hardware/vibrator/1.3/IVibrator.h> -#include <android/hardware/vibrator/BnVibratorCallback.h> #include <android/hardware/vibrator/IVibrator.h> -#include <binder/IServiceManager.h> #include "jni.h" #include <nativehelper/JNIHelp.h> @@ -28,19 +26,11 @@ #include <utils/misc.h> #include <utils/Log.h> -#include <hardware/vibrator.h> #include <inttypes.h> -#include <stdio.h> #include <vibratorservice/VibratorHalController.h> -using android::hardware::Return; -using android::hardware::Void; -using android::hardware::vibrator::V1_0::EffectStrength; -using android::hardware::vibrator::V1_0::Status; -using android::hardware::vibrator::V1_1::Effect_1_1; - namespace V1_0 = android::hardware::vibrator::V1_0; namespace V1_1 = android::hardware::vibrator::V1_1; namespace V1_2 = android::hardware::vibrator::V1_2; @@ -87,150 +77,7 @@ static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) == static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) == static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK)); -class VibratorCallback { - public: - VibratorCallback(JNIEnv *env, jobject vibration) : - mVibration(MakeGlobalRefOrDie(env, vibration)) {} - - ~VibratorCallback() { - JNIEnv *env = AndroidRuntime::getJNIEnv(); - env->DeleteGlobalRef(mVibration); - } - - void onComplete() { - auto env = AndroidRuntime::getJNIEnv(); - env->CallVoidMethod(mVibration, sMethodIdOnComplete); - } - - private: - jobject mVibration; -}; - -class AidlVibratorCallback : public aidl::BnVibratorCallback { - public: - AidlVibratorCallback(JNIEnv *env, jobject vibration) : - mCb(env, vibration) {} - - binder::Status onComplete() override { - mCb.onComplete(); - return binder::Status::ok(); // oneway, local call - } - - private: - VibratorCallback mCb; -}; - -static constexpr int NUM_TRIES = 2; - -template<class R> -inline R NoneStatus() { - using ::android::hardware::Status; - return Status::fromExceptionCode(Status::EX_NONE); -} - -template<> -inline binder::Status NoneStatus() { - using binder::Status; - return Status::fromExceptionCode(Status::EX_NONE); -} - -// Creates a Return<R> with STATUS::EX_NULL_POINTER. -template<class R> -inline R NullptrStatus() { - using ::android::hardware::Status; - return Status::fromExceptionCode(Status::EX_NULL_POINTER); -} - -template<> -inline binder::Status NullptrStatus() { - using binder::Status; - return Status::fromExceptionCode(Status::EX_NULL_POINTER); -} - -template <typename I> -sp<I> getService() { - return I::getService(); -} - -template <> -sp<aidl::IVibrator> getService() { - return waitForVintfService<aidl::IVibrator>(); -} - -template <typename I> -sp<I> tryGetService() { - return I::tryGetService(); -} - -template <> -sp<aidl::IVibrator> tryGetService() { - return checkVintfService<aidl::IVibrator>(); -} - -template <typename I> -class HalWrapper { - public: - static std::unique_ptr<HalWrapper> Create() { - // Assume that if getService returns a nullptr, HAL is not available on the - // device. - auto hal = getService<I>(); - return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr; - } - - // Helper used to transparently deal with the vibrator HAL becoming unavailable. - template<class R, class... Args0, class... Args1> - R call(R (I::* fn)(Args0...), Args1&&... args1) { - // Return<R> doesn't have a default constructor, so make a Return<R> with - // STATUS::EX_NONE. - R ret{NoneStatus<R>()}; - - // Note that ret is guaranteed to be changed after this loop. - for (int i = 0; i < NUM_TRIES; ++i) { - ret = (mHal == nullptr) ? NullptrStatus<R>() - : (*mHal.*fn)(std::forward<Args1>(args1)...); - - if (ret.isOk()) { - break; - } - - ALOGE("Failed to issue command to vibrator HAL. Retrying."); - - // Restoring connection to the HAL. - mHal = tryGetService<I>(); - } - return ret; - } - - private: - HalWrapper(sp<I> &&hal) : mHal(std::move(hal)) {} - - private: - sp<I> mHal; -}; - -template <typename I> -static auto getHal() { - static auto sHalWrapper = HalWrapper<I>::Create(); - return sHalWrapper.get(); -} - -template<class R, class I, class... Args0, class... Args1> -R halCall(R (I::* fn)(Args0...), Args1&&... args1) { - auto hal = getHal<I>(); - return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>(); -} - -template<class R> -bool isValidEffect(jlong effect) { - if (effect < 0) { - return false; - } - R val = static_cast<R>(effect); - auto iter = hardware::hidl_enum_range<R>(); - return val >= *iter.begin() && val <= *std::prev(iter.end()); -} - -static void callVibrationOnComplete(jobject vibration) { +static inline void callVibrationOnComplete(jobject vibration) { if (vibration == nullptr) { return; } @@ -257,14 +104,6 @@ static void destroyVibratorController(void* rawVibratorController) { } static jlong vibratorInit(JNIEnv* /* env */, jclass /* clazz */) { - if (auto hal = getHal<aidl::IVibrator>()) { - // IBinder::pingBinder isn't accessible as a pointer function - // but getCapabilities can serve the same purpose - int32_t cap; - hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk(); - } else { - halCall(&V1_0::IVibrator::ping).isOk(); - } std::unique_ptr<vibrator::HalController> controller = std::make_unique<vibrator::HalController>(); controller->init(); @@ -342,70 +181,19 @@ static jintArray vibratorGetSupportedEffects(JNIEnv* env, jclass /* clazz */, jl return effects; } -static jlong vibratorPerformEffect(JNIEnv* env, jclass /* clazz */, jlong effect, jlong strength, - jobject vibration, jboolean withCallback) { - if (auto hal = getHal<aidl::IVibrator>()) { - int32_t lengthMs; - sp<AidlVibratorCallback> effectCallback = - (withCallback != JNI_FALSE ? new AidlVibratorCallback(env, vibration) : nullptr); - aidl::Effect effectType(static_cast<aidl::Effect>(effect)); - aidl::EffectStrength effectStrength(static_cast<aidl::EffectStrength>(strength)); - - auto status = hal->call(&aidl::IVibrator::perform, effectType, effectStrength, effectCallback, &lengthMs); - if (!status.isOk()) { - if (status.exceptionCode() != binder::Status::EX_UNSUPPORTED_OPERATION) { - ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32 - ": %s", static_cast<int64_t>(effect), static_cast<int32_t>(strength), status.toString8().string()); - } - return -1; - } - return lengthMs; - } else { - Status status; - uint32_t lengthMs; - auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) { - status = retStatus; - lengthMs = retLengthMs; - }; - EffectStrength effectStrength(static_cast<EffectStrength>(strength)); - - Return<void> ret; - if (isValidEffect<V1_0::Effect>(effect)) { - ret = halCall(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(effect), - effectStrength, callback); - } else if (isValidEffect<Effect_1_1>(effect)) { - ret = halCall(&V1_1::IVibrator::perform_1_1, static_cast<Effect_1_1>(effect), - effectStrength, callback); - } else if (isValidEffect<V1_2::Effect>(effect)) { - ret = halCall(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(effect), - effectStrength, callback); - } else if (isValidEffect<V1_3::Effect>(effect)) { - ret = halCall(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(effect), - effectStrength, callback); - } else { - ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")", - static_cast<int32_t>(effect)); - return -1; - } - - if (!ret.isOk()) { - ALOGW("Failed to perform effect (%" PRId32 ")", static_cast<int32_t>(effect)); - return -1; - } - - if (status == Status::OK) { - return lengthMs; - } else if (status != Status::UNSUPPORTED_OPERATION) { - // Don't warn on UNSUPPORTED_OPERATION, that's a normal event and just means the motor - // doesn't have a pre-defined waveform to perform for it, so we should just give the - // opportunity to fall back to the framework waveforms. - ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32 - ", error=%" PRIu32 ").", static_cast<int64_t>(effect), - static_cast<int32_t>(strength), static_cast<uint32_t>(status)); - } +static jlong vibratorPerformEffect(JNIEnv* env, jclass /* clazz */, jlong controllerPtr, + jlong effect, jlong strength, jobject vibration) { + vibrator::HalController* controller = reinterpret_cast<vibrator::HalController*>(controllerPtr); + if (controller == nullptr) { + ALOGE("vibratorPerformEffect failed because controller was not initialized"); + return -1; } - - return -1; + aidl::Effect effectType = static_cast<aidl::Effect>(effect); + aidl::EffectStrength effectStrength = static_cast<aidl::EffectStrength>(strength); + jobject vibrationRef = vibration == nullptr ? vibration : MakeGlobalRefOrDie(env, vibration); + auto callback = [vibrationRef]() { callVibrationOnComplete(vibrationRef); }; + auto result = controller->performEffect(effectType, effectStrength, callback); + return result.isOk() ? result.value().count() : -1; } static void vibratorPerformComposedEffect(JNIEnv* env, jclass /* clazz */, jlong controllerPtr, @@ -464,7 +252,7 @@ static const JNINativeMethod method_table[] = { {"vibratorOn", "(JJLcom/android/server/VibratorService$Vibration;)V", (void*)vibratorOn}, {"vibratorOff", "(J)V", (void*)vibratorOff}, {"vibratorSetAmplitude", "(JI)V", (void*)vibratorSetAmplitude}, - {"vibratorPerformEffect", "(JJLcom/android/server/VibratorService$Vibration;Z)J", + {"vibratorPerformEffect", "(JJJLcom/android/server/VibratorService$Vibration;)J", (void*)vibratorPerformEffect}, {"vibratorPerformComposedEffect", "(J[Landroid/os/VibrationEffect$Composition$PrimitiveEffect;Lcom/android/server/" diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp index a5f0d045948c..f7082a9a1a0c 100644 --- a/services/incremental/IncrementalService.cpp +++ b/services/incremental/IncrementalService.cpp @@ -23,7 +23,6 @@ #include <android-base/properties.h> #include <android-base/stringprintf.h> #include <binder/AppOpsManager.h> -#include <binder/Nullable.h> #include <binder/Status.h> #include <sys/stat.h> #include <uuid/uuid.h> @@ -1404,7 +1403,7 @@ void IncrementalService::prepareDataLoaderLocked(IncFsMount& ifs, DataLoaderPara } FileSystemControlParcel fsControlParcel; - fsControlParcel.incremental = aidl::make_nullable<IncrementalFileSystemControlParcel>(); + fsControlParcel.incremental = std::make_optional<IncrementalFileSystemControlParcel>(); fsControlParcel.incremental->cmd.reset(dup(ifs.control.cmd())); fsControlParcel.incremental->pendingReads.reset(dup(ifs.control.pendingReads())); fsControlParcel.incremental->log.reset(dup(ifs.control.logs())); diff --git a/services/systemcaptions/java/com/android/server/systemcaptions/SystemCaptionsManagerService.java b/services/systemcaptions/java/com/android/server/systemcaptions/SystemCaptionsManagerService.java index 27a116c8043e..1586a33ba0e9 100644 --- a/services/systemcaptions/java/com/android/server/systemcaptions/SystemCaptionsManagerService.java +++ b/services/systemcaptions/java/com/android/server/systemcaptions/SystemCaptionsManagerService.java @@ -34,7 +34,8 @@ public final class SystemCaptionsManagerService extends context, com.android.internal.R.string.config_defaultSystemCaptionsManagerService), /*disallowProperty=*/ null, - /*packageUpdatePolicy=*/ PACKAGE_UPDATE_POLICY_REFRESH_EAGER); + /*packageUpdatePolicy=*/ PACKAGE_UPDATE_POLICY_REFRESH_EAGER + | PACKAGE_RESTART_POLICY_REFRESH_EAGER); } @Override diff --git a/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java index 1cb004a6dc1e..fdcadf3e3088 100644 --- a/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java @@ -25,6 +25,7 @@ import static android.location.Criteria.ACCURACY_COARSE; import static android.location.Criteria.ACCURACY_FINE; import static android.location.Criteria.POWER_HIGH; import static android.location.LocationManager.PASSIVE_PROVIDER; +import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF; import static androidx.test.ext.truth.location.LocationSubject.assertThat; @@ -907,6 +908,21 @@ public class LocationProviderManagerTest { assertThat(mProvider.getRequest().interval).isEqualTo(5); } + @Test + public void testProviderRequest_BatterySaver_ScreenOnOff() { + mInjector.getLocationPowerSaveModeHelper().setLocationPowerSaveMode( + LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF); + + ILocationListener listener = createMockLocationListener(); + LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 5, 0, false); + mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener); + + assertThat(mProvider.getRequest().reportLocation).isTrue(); + + mInjector.getScreenInteractiveHelper().setScreenInteractive(false); + assertThat(mProvider.getRequest().reportLocation).isFalse(); + } + private ILocationListener createMockLocationListener() { return spy(new ILocationListener.Stub() { @Override diff --git a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java index 7d6d90c4578c..02d10e3b6ce1 100644 --- a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java @@ -21,7 +21,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; @@ -310,7 +309,7 @@ public class VibratorServiceTest { verify(mNativeWrapperMock).vibratorPerformEffect( eq((long) VibrationEffect.EFFECT_CLICK), eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG), - any(VibratorService.Vibration.class), eq(false)); + any(VibratorService.Vibration.class)); } @Test @@ -387,21 +386,26 @@ public class VibratorServiceTest { } @Test - public void vibrate_withOneShotAndNativeCallbackNotTriggered_finishesVibrationViaFallback() { + public void vibrate_withPrebakedAndNativeCallbackTriggered_finishesVibration() { + when(mNativeWrapperMock.vibratorGetSupportedEffects()) + .thenReturn(new int[]{VibrationEffect.EFFECT_CLICK}); + doAnswer(invocation -> { + ((VibratorService.Vibration) invocation.getArgument(2)).onComplete(); + return 10_000L; // 10s + }).when(mNativeWrapperMock).vibratorPerformEffect( + anyLong(), anyLong(), any(VibratorService.Vibration.class)); VibratorService service = createService(); Mockito.clearInvocations(mNativeWrapperMock); - vibrate(service, VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE)); - - verify(mNativeWrapperMock).vibratorOff(); - verify(mNativeWrapperMock).vibratorOn(eq(100L), any(VibratorService.Vibration.class)); - Mockito.clearInvocations(mNativeWrapperMock); - - // Run the scheduled callback to finish one-shot vibration. - mTestLooper.moveTimeForward(200); - mTestLooper.dispatchAll(); + vibrate(service, VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)); - verify(mNativeWrapperMock).vibratorOff(); + InOrder inOrderVerifier = inOrder(mNativeWrapperMock); + inOrderVerifier.verify(mNativeWrapperMock).vibratorOff(); + inOrderVerifier.verify(mNativeWrapperMock).vibratorPerformEffect( + eq((long) VibrationEffect.EFFECT_CLICK), + eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG), + any(VibratorService.Vibration.class)); + inOrderVerifier.verify(mNativeWrapperMock).vibratorOff(); } @Test @@ -447,30 +451,6 @@ public class VibratorServiceTest { } @Test - public void vibrate_withComposedAndNativeCallbackNotTriggered_finishesVibrationViaFallback() { - mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); - VibratorService service = createService(); - Mockito.clearInvocations(mNativeWrapperMock); - - VibrationEffect effect = VibrationEffect.startComposition() - .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 10) - .compose(); - vibrate(service, effect); - - verify(mNativeWrapperMock).vibratorOff(); - verify(mNativeWrapperMock).vibratorPerformComposedEffect( - any(VibrationEffect.Composition.PrimitiveEffect[].class), - any(VibratorService.Vibration.class)); - Mockito.clearInvocations(mNativeWrapperMock); - - // Run the scheduled callback to finish one-shot vibration. - mTestLooper.moveTimeForward(10000); // 10s - mTestLooper.dispatchAll(); - - verify(mNativeWrapperMock).vibratorOff(); - } - - @Test public void vibrate_whenBinderDies_cancelsVibration() { mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); doAnswer(invocation -> { @@ -574,15 +554,15 @@ public class VibratorServiceTest { verify(mNativeWrapperMock).vibratorPerformEffect( eq((long) VibrationEffect.EFFECT_CLICK), - eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG), any(), anyBoolean()); + eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG), any()); verify(mNativeWrapperMock).vibratorPerformEffect( eq((long) VibrationEffect.EFFECT_TICK), - eq((long) VibrationEffect.EFFECT_STRENGTH_MEDIUM), any(), anyBoolean()); + eq((long) VibrationEffect.EFFECT_STRENGTH_MEDIUM), any()); verify(mNativeWrapperMock).vibratorPerformEffect( eq((long) VibrationEffect.EFFECT_DOUBLE_CLICK), - eq((long) VibrationEffect.EFFECT_STRENGTH_LIGHT), any(), anyBoolean()); + eq((long) VibrationEffect.EFFECT_STRENGTH_LIGHT), any()); verify(mNativeWrapperMock, never()).vibratorPerformEffect( - eq((long) VibrationEffect.EFFECT_HEAVY_CLICK), anyLong(), any(), anyBoolean()); + eq((long) VibrationEffect.EFFECT_HEAVY_CLICK), anyLong(), any()); } @Test diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java index 80f145b16147..35d6f470a504 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java @@ -48,7 +48,7 @@ public class PackageManagerServiceTest { public void sendPackageBroadcast(final String action, final String pkg, final Bundle extras, final int flags, final String targetPkg, final IIntentReceiver finishedReceiver, final int[] userIds, - int[] instantUserIds, SparseArray<int[]> broadcastWhitelist) { + int[] instantUserIds, SparseArray<int[]> broadcastAllowList) { } public void sendPackageAddedForNewUsers(String packageName, diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt index 9f9ec31f0c91..f96ebda67602 100644 --- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt +++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt @@ -23,6 +23,8 @@ import com.google.common.truth.Expect import org.junit.Rule import org.junit.Test +import org.junit.rules.Timeout +import java.util.concurrent.TimeUnit /** * Collects APKs from the device and verifies that the new parsing behavior outputs @@ -32,6 +34,9 @@ import org.junit.Test class AndroidPackageParsingEquivalenceTest : AndroidPackageParsingTestBase() { @get:Rule + val timeout = Timeout(4, TimeUnit.MINUTES) + + @get:Rule val expect = Expect.create() @Test diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java index dcf319058ca2..e5e931115c05 100644 --- a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java @@ -27,6 +27,9 @@ import android.app.timezonedetector.TimeZoneCapabilities; import android.app.timezonedetector.TimeZoneConfiguration; import android.util.IndentingPrintWriter; +import java.util.ArrayList; +import java.util.List; + class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy { private StrategyListener mListener; @@ -41,6 +44,7 @@ class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy { private TelephonyTimeZoneSuggestion mLastTelephonySuggestion; private boolean mHandleAutoTimeZoneConfigChangedCalled; private boolean mDumpCalled; + private final List<Dumpable> mDumpables = new ArrayList<>(); @Override public void setStrategyListener(@NonNull StrategyListener listener) { @@ -105,7 +109,7 @@ class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy { @Override public void addDumpable(Dumpable dumpable) { - // Stubbed + mDumpables.add(dumpable); } @Override @@ -149,4 +153,8 @@ class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy { void verifyDumpCalled() { assertTrue(mDumpCalled); } + + void verifyHasDumpable(Dumpable expected) { + assertTrue(mDumpables.contains(expected)); + } } diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java index 0e2c22756097..e9d57e52ce69 100644 --- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java @@ -75,6 +75,16 @@ public class TimeZoneDetectorInternalImplTest { mFakeTimeZoneDetectorStrategy.verifySuggestGeolocationTimeZoneCalled(timeZoneSuggestion); } + @Test + public void testAddDumpable() throws Exception { + Dumpable stubbedDumpable = mock(Dumpable.class); + + mTimeZoneDetectorInternal.addDumpable(stubbedDumpable); + mTestHandler.assertTotalMessagesEnqueued(0); + + mFakeTimeZoneDetectorStrategy.verifyHasDumpable(stubbedDumpable); + } + private static GeolocationTimeZoneSuggestion createGeolocationTimeZoneSuggestion() { return new GeolocationTimeZoneSuggestion(ARBITRARY_ZONE_IDS); } diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java index 8034cacc6923..3a1ec4f90d7a 100644 --- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java @@ -52,6 +52,7 @@ import org.junit.runner.RunWith; import java.io.PrintWriter; import java.io.StringWriter; +import java.util.Arrays; @RunWith(AndroidJUnit4.class) public class TimeZoneDetectorServiceTest { @@ -253,6 +254,39 @@ public class TimeZoneDetectorServiceTest { } @Test(expected = SecurityException.class) + public void testSuggestGeolocationTimeZone_withoutPermission() { + doThrow(new SecurityException("Mock")) + .when(mMockContext).enforceCallingOrSelfPermission(anyString(), any()); + GeolocationTimeZoneSuggestion timeZoneSuggestion = createGeolocationTimeZoneSuggestion(); + + try { + mTimeZoneDetectorService.suggestGeolocationTimeZone(timeZoneSuggestion); + fail(); + } finally { + verify(mMockContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.SET_TIME_ZONE), + anyString()); + } + } + + @Test + public void testSuggestGeolocationTimeZone() throws Exception { + doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any()); + + GeolocationTimeZoneSuggestion timeZoneSuggestion = createGeolocationTimeZoneSuggestion(); + + mTimeZoneDetectorService.suggestGeolocationTimeZone(timeZoneSuggestion); + mTestHandler.assertTotalMessagesEnqueued(1); + + verify(mMockContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.SET_TIME_ZONE), + anyString()); + + mTestHandler.waitForMessagesToBeProcessed(); + mFakeTimeZoneDetectorStrategy.verifySuggestGeolocationTimeZoneCalled(timeZoneSuggestion); + } + + @Test(expected = SecurityException.class) public void testSuggestManualTimeZone_withoutPermission() { doThrow(new SecurityException("Mock")) .when(mMockContext).enforceCallingOrSelfPermission(anyString(), any()); @@ -346,7 +380,7 @@ public class TimeZoneDetectorServiceTest { } @Test - public void testAutoTimeZoneDetectionChanged() throws Exception { + public void testHandleAutoTimeZoneConfigChanged() throws Exception { mTimeZoneDetectorService.handleAutoTimeZoneConfigChanged(); mTestHandler.assertTotalMessagesEnqueued(1); mTestHandler.waitForMessagesToBeProcessed(); @@ -370,10 +404,15 @@ public class TimeZoneDetectorServiceTest { private static TimeZoneCapabilities createTimeZoneCapabilities() { return new TimeZoneCapabilities.Builder(ARBITRARY_USER_ID) .setConfigureAutoDetectionEnabled(CAPABILITY_POSSESSED) + .setConfigureGeoDetectionEnabled(CAPABILITY_POSSESSED) .setSuggestManualTimeZone(CAPABILITY_POSSESSED) .build(); } + private static GeolocationTimeZoneSuggestion createGeolocationTimeZoneSuggestion() { + return new GeolocationTimeZoneSuggestion(Arrays.asList("TestZoneId")); + } + private static ManualTimeZoneSuggestion createManualTimeZoneSuggestion() { return new ManualTimeZoneSuggestion("TestZoneId"); } diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java index 68554451e43a..a6caa4299ef6 100644 --- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java @@ -41,6 +41,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.timezonedetector.ManualTimeZoneSuggestion; import android.app.timezonedetector.TelephonyTimeZoneSuggestion; @@ -56,10 +57,10 @@ import org.junit.Before; import org.junit.Test; import java.io.StringWriter; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; +import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; @@ -93,16 +94,26 @@ public class TimeZoneDetectorStrategyImplTest { TELEPHONY_SCORE_HIGHEST), }; - private static final TimeZoneConfiguration CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED = + private static final TimeZoneConfiguration CONFIG_AUTO_ENABLED = new TimeZoneConfiguration.Builder() .setAutoDetectionEnabled(true) .build(); - private static final TimeZoneConfiguration CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED = + private static final TimeZoneConfiguration CONFIG_AUTO_DISABLED = new TimeZoneConfiguration.Builder() .setAutoDetectionEnabled(false) .build(); + private static final TimeZoneConfiguration CONFIG_GEO_DETECTION_DISABLED = + new TimeZoneConfiguration.Builder() + .setGeoDetectionEnabled(false) + .build(); + + private static final TimeZoneConfiguration CONFIG_GEO_DETECTION_ENABLED = + new TimeZoneConfiguration.Builder() + .setGeoDetectionEnabled(true) + .build(); + private TimeZoneDetectorStrategyImpl mTimeZoneDetectorStrategy; private FakeCallback mFakeCallback; private MockStrategyListener mMockStrategyListener; @@ -120,7 +131,7 @@ public class TimeZoneDetectorStrategyImplTest { public void testGetCapabilities() { new Script() .initializeUser(USER_ID, UserCase.UNRESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED); + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED)); TimeZoneCapabilities expectedCapabilities = mFakeCallback.getCapabilities(USER_ID); assertEquals(expectedCapabilities, mTimeZoneDetectorStrategy.getCapabilities(USER_ID)); } @@ -129,7 +140,7 @@ public class TimeZoneDetectorStrategyImplTest { public void testGetConfiguration() { new Script() .initializeUser(USER_ID, UserCase.UNRESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED); + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED)); TimeZoneConfiguration expectedConfiguration = mFakeCallback.getConfiguration(USER_ID); assertTrue(expectedConfiguration.isComplete()); assertEquals(expectedConfiguration, mTimeZoneDetectorStrategy.getConfiguration(USER_ID)); @@ -140,20 +151,22 @@ public class TimeZoneDetectorStrategyImplTest { Script script = new Script(); script.initializeUser(USER_ID, UserCase.UNRESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED); + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED)); { // Check the fake test infra is doing what is expected. TimeZoneCapabilities capabilities = mFakeCallback.getCapabilities(USER_ID); assertEquals(CAPABILITY_POSSESSED, capabilities.getConfigureAutoDetectionEnabled()); + assertEquals(CAPABILITY_POSSESSED, capabilities.getConfigureGeoDetectionEnabled()); assertEquals(CAPABILITY_NOT_APPLICABLE, capabilities.getSuggestManualTimeZone()); } script.initializeUser(USER_ID, UserCase.UNRESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED); + CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED)); { // Check the fake test infra is doing what is expected. TimeZoneCapabilities capabilities = mFakeCallback.getCapabilities(USER_ID); assertEquals(CAPABILITY_POSSESSED, capabilities.getConfigureAutoDetectionEnabled()); + assertEquals(CAPABILITY_POSSESSED, capabilities.getConfigureGeoDetectionEnabled()); assertEquals(CAPABILITY_POSSESSED, capabilities.getSuggestManualTimeZone()); } } @@ -163,20 +176,22 @@ public class TimeZoneDetectorStrategyImplTest { Script script = new Script(); script.initializeUser(USER_ID, UserCase.RESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED); + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED)); { // Check the fake test infra is doing what is expected. TimeZoneCapabilities capabilities = mFakeCallback.getCapabilities(USER_ID); assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getConfigureAutoDetectionEnabled()); + assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getConfigureGeoDetectionEnabled()); assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSuggestManualTimeZone()); } script.initializeUser(USER_ID, UserCase.RESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED); + CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED)); { // Check the fake test infra is doing what is expected. TimeZoneCapabilities capabilities = mFakeCallback.getCapabilities(USER_ID); assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getConfigureAutoDetectionEnabled()); + assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getConfigureGeoDetectionEnabled()); assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSuggestManualTimeZone()); } } @@ -186,20 +201,22 @@ public class TimeZoneDetectorStrategyImplTest { Script script = new Script(); script.initializeUser(USER_ID, UserCase.AUTO_DETECT_NOT_SUPPORTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED); + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED)); { // Check the fake test infra is doing what is expected. TimeZoneCapabilities capabilities = mFakeCallback.getCapabilities(USER_ID); assertEquals(CAPABILITY_NOT_SUPPORTED, capabilities.getConfigureAutoDetectionEnabled()); + assertEquals(CAPABILITY_NOT_SUPPORTED, capabilities.getConfigureGeoDetectionEnabled()); assertEquals(CAPABILITY_POSSESSED, capabilities.getSuggestManualTimeZone()); } script.initializeUser(USER_ID, UserCase.AUTO_DETECT_NOT_SUPPORTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED); + CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED)); { // Check the fake test infra is doing what is expected. TimeZoneCapabilities capabilities = mFakeCallback.getCapabilities(USER_ID); assertEquals(CAPABILITY_NOT_SUPPORTED, capabilities.getConfigureAutoDetectionEnabled()); + assertEquals(CAPABILITY_NOT_SUPPORTED, capabilities.getConfigureGeoDetectionEnabled()); assertEquals(CAPABILITY_POSSESSED, capabilities.getSuggestManualTimeZone()); } } @@ -208,42 +225,61 @@ public class TimeZoneDetectorStrategyImplTest { public void testUpdateConfiguration_unrestricted() { Script script = new Script() .initializeUser(USER_ID, UserCase.UNRESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED); + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED)); // Set the configuration with auto detection enabled. - script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED); + script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */); // Nothing should have happened: it was initialized in this state. script.verifyConfigurationNotChanged(); // Update the configuration with auto detection disabled. - script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED); + script.simulateUpdateConfiguration( + USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */); // The settings should have been changed and the StrategyListener onChange() called. - script.verifyConfigurationChangedAndReset( - USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED); + script.verifyConfigurationChangedAndReset(USER_ID, + CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED)); // Update the configuration with auto detection enabled. - script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED); + script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */); // The settings should have been changed and the StrategyListener onChange() called. - script.verifyConfigurationChangedAndReset(USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED); + script.verifyConfigurationChangedAndReset(USER_ID, + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED)); + + // Update the configuration to enable geolocation time zone detection. + script.simulateUpdateConfiguration( + USER_ID, CONFIG_GEO_DETECTION_ENABLED, true /* expectedResult */); + + // The settings should have been changed and the StrategyListener onChange() called. + script.verifyConfigurationChangedAndReset(USER_ID, + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_ENABLED)); } @Test public void testUpdateConfiguration_restricted() { Script script = new Script() .initializeUser(USER_ID, UserCase.RESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED); + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED)); // Try to update the configuration with auto detection disabled. - script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED); + script.simulateUpdateConfiguration( + USER_ID, CONFIG_AUTO_DISABLED, false /* expectedResult */); // The settings should not have been changed: user shouldn't have the capabilities. script.verifyConfigurationNotChanged(); // Update the configuration with auto detection enabled. - script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED); + script.simulateUpdateConfiguration( + USER_ID, CONFIG_AUTO_ENABLED, false /* expectedResult */); + + // The settings should not have been changed: user shouldn't have the capabilities. + script.verifyConfigurationNotChanged(); + + // Update the configuration to enable geolocation time zone detection. + script.simulateUpdateConfiguration( + USER_ID, CONFIG_GEO_DETECTION_ENABLED, false /* expectedResult */); // The settings should not have been changed: user shouldn't have the capabilities. script.verifyConfigurationNotChanged(); @@ -253,16 +289,18 @@ public class TimeZoneDetectorStrategyImplTest { public void testUpdateConfiguration_autoDetectNotSupported() { Script script = new Script() .initializeUser(USER_ID, UserCase.AUTO_DETECT_NOT_SUPPORTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED); + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED)); // Try to update the configuration with auto detection disabled. - script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED); + script.simulateUpdateConfiguration( + USER_ID, CONFIG_AUTO_DISABLED, false /* expectedResult */); // The settings should not have been changed: user shouldn't have the capabilities. script.verifyConfigurationNotChanged(); // Update the configuration with auto detection enabled. - script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED); + script.simulateUpdateConfiguration( + USER_ID, CONFIG_AUTO_ENABLED, false /* expectedResult */); // The settings should not have been changed: user shouldn't have the capabilities. script.verifyConfigurationNotChanged(); @@ -276,7 +314,7 @@ public class TimeZoneDetectorStrategyImplTest { createEmptySlotIndex2Suggestion(); Script script = new Script() .initializeUser(USER_ID, UserCase.UNRESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED) + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED)) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); script.simulateTelephonyTimeZoneSuggestion(slotIndex1TimeZoneSuggestion) @@ -308,6 +346,10 @@ public class TimeZoneDetectorStrategyImplTest { mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests()); } + /** + * Telephony suggestions have quality metadata. Ordinarily, low scoring suggestions are not + * used, but this is not true if the device's time zone setting is uninitialized. + */ @Test public void testTelephonySuggestionsWhenTimeZoneUninitialized() { assertTrue(TELEPHONY_SCORE_LOW < TELEPHONY_SCORE_USAGE_THRESHOLD); @@ -319,7 +361,7 @@ public class TimeZoneDetectorStrategyImplTest { Script script = new Script() .initializeUser(USER_ID, UserCase.UNRESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED); + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED)); // A low quality suggestions will not be taken: The device time zone setting is left // uninitialized. @@ -376,16 +418,16 @@ public class TimeZoneDetectorStrategyImplTest { /** * Confirms that toggling the auto time zone detection setting has the expected behavior when - * the strategy is "opinionated". + * the strategy is "opinionated" when using telephony auto detection. */ @Test - public void testTogglingAutoTimeZoneDetection() { + public void testTogglingAutoDetection_autoTelephony() { Script script = new Script(); for (TelephonyTestCase testCase : TELEPHONY_TEST_CASES) { // Start with the device in a known state. script.initializeUser(USER_ID, UserCase.UNRESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED) + CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED)) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); TelephonyTimeZoneSuggestion suggestion = @@ -405,7 +447,8 @@ public class TimeZoneDetectorStrategyImplTest { mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests()); // Toggling the time zone setting on should cause the device setting to be set. - script.simulateAutoTimeZoneDetectionEnabled(USER_ID, true); + script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, + true /* expectedResult */); // When time zone detection is already enabled the suggestion (if it scores highly // enough) should be set immediately. @@ -422,7 +465,8 @@ public class TimeZoneDetectorStrategyImplTest { mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests()); // Toggling the time zone setting should off should do nothing. - script.simulateAutoTimeZoneDetectionEnabled(USER_ID, false) + script.simulateUpdateConfiguration( + USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */) .verifyTimeZoneNotChanged(); // Assert internal service state. @@ -437,7 +481,7 @@ public class TimeZoneDetectorStrategyImplTest { public void testTelephonySuggestionsSingleSlotId() { Script script = new Script() .initializeUser(USER_ID, UserCase.UNRESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED) + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED)) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); for (TelephonyTestCase testCase : TELEPHONY_TEST_CASES) { @@ -451,8 +495,7 @@ public class TimeZoneDetectorStrategyImplTest { */ // Each test case will have the same or lower score than the last. - ArrayList<TelephonyTestCase> descendingCasesByScore = - new ArrayList<>(Arrays.asList(TELEPHONY_TEST_CASES)); + List<TelephonyTestCase> descendingCasesByScore = list(TELEPHONY_TEST_CASES); Collections.reverse(descendingCasesByScore); for (TelephonyTestCase testCase : descendingCasesByScore) { @@ -504,7 +547,7 @@ public class TimeZoneDetectorStrategyImplTest { Script script = new Script() .initializeUser(USER_ID, UserCase.UNRESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED) + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED)) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID) // Initialize the latest suggestions as empty so we don't need to worry about nulls // below for the first loop. @@ -583,15 +626,15 @@ public class TimeZoneDetectorStrategyImplTest { } /** - * The {@link TimeZoneDetectorStrategyImpl.Callback} is left to detect whether changing - * the time zone is actually necessary. This test proves that the service doesn't assume it - * knows the current setting. + * The {@link TimeZoneDetectorStrategyImpl.Callback} is left to detect whether changing the time + * zone is actually necessary. This test proves that the strategy doesn't assume it knows the + * current settings. */ @Test - public void testTelephonySuggestionTimeZoneDetectorStrategyDoesNotAssumeCurrentSetting() { + public void testTelephonySuggestionStrategyDoesNotAssumeCurrentSetting_autoTelephony() { Script script = new Script() .initializeUser(USER_ID, UserCase.UNRESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED); + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED)); TelephonyTestCase testCase = newTelephonyTestCase( MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET, QUALITY_SINGLE_ZONE, TELEPHONY_SCORE_HIGH); @@ -609,26 +652,40 @@ public class TimeZoneDetectorStrategyImplTest { // Toggling time zone detection should set the device time zone only if the current setting // value is different from the most recent telephony suggestion. - script.simulateAutoTimeZoneDetectionEnabled(USER_ID, false) + script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */) .verifyTimeZoneNotChanged() - .simulateAutoTimeZoneDetectionEnabled(USER_ID, true) + .simulateUpdateConfiguration( + USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */) .verifyTimeZoneNotChanged(); // Simulate a user turning auto detection off, a new suggestion being made while auto // detection is off, and the user turning it on again. - script.simulateAutoTimeZoneDetectionEnabled(USER_ID, false) + script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */) .simulateTelephonyTimeZoneSuggestion(newYorkSuggestion) .verifyTimeZoneNotChanged(); // Latest suggestion should be used. - script.simulateAutoTimeZoneDetectionEnabled(USER_ID, true) + script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */) .verifyTimeZoneChangedAndReset(newYorkSuggestion); } @Test - public void testManualSuggestion_unrestricted_simulateAutoTimeZoneEnabled() { + public void testManualSuggestion_autoDetectionEnabled_autoTelephony() { + checkManualSuggestion_autoDetectionEnabled(false /* geoDetectionEnabled */); + } + + @Test + public void testManualSuggestion_autoDetectionEnabled_autoGeo() { + checkManualSuggestion_autoDetectionEnabled(true /* geoDetectionEnabled */); + } + + private void checkManualSuggestion_autoDetectionEnabled(boolean geoDetectionEnabled) { + TimeZoneConfiguration geoTzEnabledConfig = + new TimeZoneConfiguration.Builder() + .setGeoDetectionEnabled(geoDetectionEnabled) + .build(); Script script = new Script() .initializeUser(USER_ID, UserCase.UNRESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED) + CONFIG_AUTO_ENABLED.with(geoTzEnabledConfig)) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); // Auto time zone detection is enabled so the manual suggestion should be ignored. @@ -641,7 +698,7 @@ public class TimeZoneDetectorStrategyImplTest { public void testManualSuggestion_restricted_simulateAutoTimeZoneEnabled() { Script script = new Script() .initializeUser(USER_ID, UserCase.RESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED) + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED)) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); // Auto time zone detection is enabled so the manual suggestion should be ignored. @@ -654,7 +711,7 @@ public class TimeZoneDetectorStrategyImplTest { public void testManualSuggestion_autoDetectNotSupported_simulateAutoTimeZoneEnabled() { Script script = new Script() .initializeUser(USER_ID, UserCase.AUTO_DETECT_NOT_SUPPORTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED) + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED)) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); // Auto time zone detection is enabled so the manual suggestion should be ignored. @@ -668,7 +725,7 @@ public class TimeZoneDetectorStrategyImplTest { public void testManualSuggestion_unrestricted_autoTimeZoneDetectionDisabled() { Script script = new Script() .initializeUser(USER_ID, UserCase.UNRESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED) + CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED)) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); // Auto time zone detection is disabled so the manual suggestion should be used. @@ -682,7 +739,7 @@ public class TimeZoneDetectorStrategyImplTest { public void testManualSuggestion_restricted_autoTimeZoneDetectionDisabled() { Script script = new Script() .initializeUser(USER_ID, UserCase.RESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED) + CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED)) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); // Restricted users do not have the capability. @@ -696,7 +753,7 @@ public class TimeZoneDetectorStrategyImplTest { public void testManualSuggestion_autoDetectNotSupported_autoTimeZoneDetectionDisabled() { Script script = new Script() .initializeUser(USER_ID, UserCase.AUTO_DETECT_NOT_SUPPORTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED) + CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED)) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); // Unrestricted users have the capability. @@ -707,10 +764,261 @@ public class TimeZoneDetectorStrategyImplTest { } @Test + public void testGeoSuggestion_uncertain() { + Script script = new Script() + .initializeUser(USER_ID, UserCase.UNRESTRICTED, + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_ENABLED)) + .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); + + GeolocationTimeZoneSuggestion uncertainSuggestion = createUncertainGeoLocationSuggestion(); + + script.simulateGeolocationTimeZoneSuggestion(uncertainSuggestion) + .verifyTimeZoneNotChanged(); + + // Assert internal service state. + assertEquals(uncertainSuggestion, + mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion()); + } + + @Test + public void testGeoSuggestion_noZones() { + Script script = new Script() + .initializeUser(USER_ID, UserCase.UNRESTRICTED, + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_ENABLED)) + .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); + + GeolocationTimeZoneSuggestion noZonesSuggestion = createGeoLocationSuggestion(list()); + + script.simulateGeolocationTimeZoneSuggestion(noZonesSuggestion) + .verifyTimeZoneNotChanged(); + + // Assert internal service state. + assertEquals(noZonesSuggestion, mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion()); + } + + @Test + public void testGeoSuggestion_oneZone() { + GeolocationTimeZoneSuggestion suggestion = + createGeoLocationSuggestion(list("Europe/London")); + + Script script = new Script() + .initializeUser(USER_ID, UserCase.UNRESTRICTED, + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_ENABLED)) + .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); + + script.simulateGeolocationTimeZoneSuggestion(suggestion) + .verifyTimeZoneChangedAndReset("Europe/London"); + + // Assert internal service state. + assertEquals(suggestion, mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion()); + } + + /** + * In the current implementation, the first zone ID is always used unless the device is set to + * one of the other options. This is "stickiness" - the device favors the zone it is currently + * set to until that unambiguously can't be correct. + */ + @Test + public void testGeoSuggestion_multiZone() { + GeolocationTimeZoneSuggestion londonOnlySuggestion = + createGeoLocationSuggestion(list("Europe/London")); + GeolocationTimeZoneSuggestion londonOrParisSuggestion = + createGeoLocationSuggestion(list("Europe/Paris", "Europe/London")); + GeolocationTimeZoneSuggestion parisOnlySuggestion = + createGeoLocationSuggestion(list("Europe/Paris")); + + Script script = new Script() + .initializeUser(USER_ID, UserCase.UNRESTRICTED, + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_ENABLED)) + .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); + + script.simulateGeolocationTimeZoneSuggestion(londonOnlySuggestion) + .verifyTimeZoneChangedAndReset("Europe/London"); + assertEquals(londonOnlySuggestion, + mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion()); + + // Confirm bias towards the current device zone when there's multiple zones to choose from. + script.simulateGeolocationTimeZoneSuggestion(londonOrParisSuggestion) + .verifyTimeZoneNotChanged(); + assertEquals(londonOrParisSuggestion, + mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion()); + + script.simulateGeolocationTimeZoneSuggestion(parisOnlySuggestion) + .verifyTimeZoneChangedAndReset("Europe/Paris"); + assertEquals(parisOnlySuggestion, + mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion()); + + // Now the suggestion that previously left the device on Europe/London will leave the device + // on Europe/Paris. + script.simulateGeolocationTimeZoneSuggestion(londonOrParisSuggestion) + .verifyTimeZoneNotChanged(); + assertEquals(londonOrParisSuggestion, + mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion()); + } + + /** + * Confirms that toggling the auto time zone detection enabled setting has the expected behavior + * when the strategy is "opinionated" and "un-opinionated" when in geolocation detection is + * enabled. + */ + @Test + public void testTogglingAutoDetectionEnabled_autoGeo() { + GeolocationTimeZoneSuggestion geolocationSuggestion = + createGeoLocationSuggestion(list("Europe/London")); + GeolocationTimeZoneSuggestion uncertainGeolocationSuggestion = + createUncertainGeoLocationSuggestion(); + ManualTimeZoneSuggestion manualSuggestion = createManualSuggestion("Europe/Paris"); + + Script script = new Script() + .initializeUser(USER_ID, UserCase.UNRESTRICTED, + CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_ENABLED)) + .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); + + script.simulateGeolocationTimeZoneSuggestion(geolocationSuggestion); + + // When time zone detection is not enabled, the time zone suggestion will not be set. + script.verifyTimeZoneNotChanged(); + + // Assert internal service state. + assertEquals(geolocationSuggestion, + mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion()); + + // Toggling the time zone setting on should cause the device setting to be set. + script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */) + .verifyTimeZoneChangedAndReset("Europe/London"); + + // Toggling the time zone setting should off should do nothing because the device is now + // set to that time zone. + script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */) + .verifyTimeZoneNotChanged() + .simulateUpdateConfiguration( + USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */) + .verifyTimeZoneNotChanged(); + + // Now toggle auto time zone setting, and confirm it is opinionated. + script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */) + .simulateManualTimeZoneSuggestion( + USER_ID, manualSuggestion, true /* expectedResult */) + .verifyTimeZoneChangedAndReset(manualSuggestion) + .simulateUpdateConfiguration( + USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */) + .verifyTimeZoneChangedAndReset("Europe/London"); + + // Now withdraw the geolocation suggestion, and assert the strategy is no longer + // opinionated. + /* expectedResult */ + script.simulateGeolocationTimeZoneSuggestion(uncertainGeolocationSuggestion) + .verifyTimeZoneNotChanged() + .simulateUpdateConfiguration( + USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */) + .verifyTimeZoneNotChanged() + .simulateManualTimeZoneSuggestion( + USER_ID, manualSuggestion, true /* expectedResult */) + .verifyTimeZoneChangedAndReset(manualSuggestion) + .simulateUpdateConfiguration( + USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */) + .verifyTimeZoneNotChanged(); + + // Assert internal service state. + assertEquals(uncertainGeolocationSuggestion, + mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion()); + } + + /** + * Confirms that changing the geolocation time zone detection enabled setting has the expected + * behavior, i.e. immediately recompute the detected time zone using different signals. + */ + @Test + public void testChangingGeoDetectionEnabled() { + GeolocationTimeZoneSuggestion geolocationSuggestion = + createGeoLocationSuggestion(list("Europe/London")); + TelephonyTimeZoneSuggestion telephonySuggestion = createTelephonySuggestion( + SLOT_INDEX1, MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET, QUALITY_SINGLE_ZONE, + "Europe/Paris"); + + Script script = new Script() + .initializeUser(USER_ID, UserCase.UNRESTRICTED, + CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED)) + .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); + + // Add suggestions. Nothing should happen as time zone detection is disabled. + script.simulateGeolocationTimeZoneSuggestion(geolocationSuggestion) + .verifyTimeZoneNotChanged(); + script.simulateTelephonyTimeZoneSuggestion(telephonySuggestion) + .verifyTimeZoneNotChanged(); + + // Assert internal service state. + assertEquals(geolocationSuggestion, + mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion()); + assertEquals(telephonySuggestion, + mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1).suggestion); + + // Toggling the time zone detection enabled setting on should cause the device setting to be + // set from the telephony signal, as we've started with geolocation time zone detection + // disabled. + script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */) + .verifyTimeZoneChangedAndReset(telephonySuggestion); + + // Changing the detection to enable geo detection should cause the device tz setting to + // change to the geo suggestion. + script.simulateUpdateConfiguration( + USER_ID, CONFIG_GEO_DETECTION_ENABLED, true /* expectedResult */) + .verifyTimeZoneChangedAndReset(geolocationSuggestion.getZoneIds().get(0)); + + // Changing the detection to disable geo detection should cause the device tz setting to + // change to the telephony suggestion. + script.simulateUpdateConfiguration( + USER_ID, CONFIG_GEO_DETECTION_DISABLED, true /* expectedResult */) + .verifyTimeZoneChangedAndReset(telephonySuggestion); + } + + /** + * The {@link TimeZoneDetectorStrategyImpl.Callback} is left to detect whether changing the time + * zone is actually necessary. This test proves that the strategy doesn't assume it knows the + * current setting. + */ + @Test + public void testTimeZoneDetectorStrategyDoesNotAssumeCurrentSetting_autoGeo() { + GeolocationTimeZoneSuggestion losAngelesSuggestion = + createGeoLocationSuggestion(list("America/Los_Angeles")); + GeolocationTimeZoneSuggestion newYorkSuggestion = + createGeoLocationSuggestion(list("America/New_York")); + + Script script = new Script() + .initializeUser(USER_ID, UserCase.UNRESTRICTED, + CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_ENABLED)); + + // Initialization. + script.simulateGeolocationTimeZoneSuggestion(losAngelesSuggestion) + .verifyTimeZoneChangedAndReset("America/Los_Angeles"); + // Suggest it again - it should not be set because it is already set. + script.simulateGeolocationTimeZoneSuggestion(losAngelesSuggestion) + .verifyTimeZoneNotChanged(); + + // Toggling time zone detection should set the device time zone only if the current setting + // value is different from the most recent telephony suggestion. + /* expectedResult */ + script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */) + .verifyTimeZoneNotChanged() + .simulateUpdateConfiguration( + USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */) + .verifyTimeZoneNotChanged(); + + // Simulate a user turning auto detection off, a new suggestion being made while auto + // detection is off, and the user turning it on again. + script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */) + .simulateGeolocationTimeZoneSuggestion(newYorkSuggestion) + .verifyTimeZoneNotChanged(); + // Latest suggestion should be used. + script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */) + .verifyTimeZoneChangedAndReset("America/New_York"); + } + + @Test public void testAddDumpable() { new Script() .initializeUser(USER_ID, UserCase.UNRESTRICTED, - CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED) + CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED)) .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID); AtomicBoolean dumpCalled = new AtomicBoolean(false); @@ -733,6 +1041,15 @@ public class TimeZoneDetectorStrategyImplTest { return new ManualTimeZoneSuggestion(zoneId); } + private static TelephonyTimeZoneSuggestion createTelephonySuggestion( + int slotIndex, @MatchType int matchType, @Quality int quality, String zoneId) { + return new TelephonyTimeZoneSuggestion.Builder(slotIndex) + .setMatchType(matchType) + .setQuality(quality) + .setZoneId(zoneId) + .build(); + } + private static TelephonyTimeZoneSuggestion createEmptySlotIndex1Suggestion() { return new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX1).build(); } @@ -741,6 +1058,17 @@ public class TimeZoneDetectorStrategyImplTest { return new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX2).build(); } + private static GeolocationTimeZoneSuggestion createUncertainGeoLocationSuggestion() { + return createGeoLocationSuggestion(null); + } + + private static GeolocationTimeZoneSuggestion createGeoLocationSuggestion( + @Nullable List<String> zoneIds) { + GeolocationTimeZoneSuggestion suggestion = new GeolocationTimeZoneSuggestion(zoneIds); + suggestion.addDebugInfo("Test suggestion"); + return suggestion; + } + static class FakeCallback implements TimeZoneDetectorStrategyImpl.Callback { private TimeZoneCapabilities mCapabilities; @@ -757,7 +1085,8 @@ public class TimeZoneDetectorStrategyImplTest { TimeZoneConfiguration configuration) { assertEquals(userId, capabilities.getUserId()); mCapabilities = capabilities; - assertTrue(configuration.isComplete()); + assertTrue("Configuration must be complete when initializing, config=" + configuration, + configuration.isComplete()); mConfiguration.init(new UserConfiguration(userId, configuration)); } @@ -790,11 +1119,8 @@ public class TimeZoneDetectorStrategyImplTest { mConfiguration.set(new UserConfiguration(userId, newConfig)); if (!newConfig.equals(oldConfig)) { - if (oldConfig.isAutoDetectionEnabled() != newConfig.isAutoDetectionEnabled()) { - // Simulate what happens when the auto detection enabled configuration is - // changed. - mStrategy.handleAutoTimeZoneConfigChanged(); - } + // Simulate what happens when the auto detection configuration is changed. + mStrategy.handleAutoTimeZoneConfigChanged(); } } @@ -804,6 +1130,11 @@ public class TimeZoneDetectorStrategyImplTest { } @Override + public boolean isGeoDetectionEnabled() { + return mConfiguration.getLatest().configuration.isGeoDetectionEnabled(); + } + + @Override public boolean isDeviceTimeZoneInitialized() { return mTimeZoneId.getLatest() != null; } @@ -942,32 +1273,33 @@ public class TimeZoneDetectorStrategyImplTest { * supplied configuration. */ private static TimeZoneCapabilities createCapabilities( - int userId, UserCase userRole, TimeZoneConfiguration configuration) { - switch (userRole) { + int userId, UserCase userCase, TimeZoneConfiguration configuration) { + switch (userCase) { case UNRESTRICTED: { int suggestManualTimeZoneCapability = configuration.isAutoDetectionEnabled() ? CAPABILITY_NOT_APPLICABLE : CAPABILITY_POSSESSED; return new TimeZoneCapabilities.Builder(userId) .setConfigureAutoDetectionEnabled(CAPABILITY_POSSESSED) + .setConfigureGeoDetectionEnabled(CAPABILITY_POSSESSED) .setSuggestManualTimeZone(suggestManualTimeZoneCapability) .build(); } case RESTRICTED: { return new TimeZoneCapabilities.Builder(userId) .setConfigureAutoDetectionEnabled(CAPABILITY_NOT_ALLOWED) + .setConfigureGeoDetectionEnabled(CAPABILITY_NOT_ALLOWED) .setSuggestManualTimeZone(CAPABILITY_NOT_ALLOWED) .build(); - } case AUTO_DETECT_NOT_SUPPORTED: { return new TimeZoneCapabilities.Builder(userId) .setConfigureAutoDetectionEnabled(CAPABILITY_NOT_SUPPORTED) + .setConfigureGeoDetectionEnabled(CAPABILITY_NOT_SUPPORTED) .setSuggestManualTimeZone(CAPABILITY_POSSESSED) .build(); - } default: - throw new AssertionError(userRole + " not recognized"); + throw new AssertionError(userCase + " not recognized"); } } @@ -978,8 +1310,8 @@ public class TimeZoneDetectorStrategyImplTest { private class Script { Script initializeUser( - @UserIdInt int userId, UserCase userRole, TimeZoneConfiguration configuration) { - TimeZoneCapabilities capabilities = createCapabilities(userId, userRole, configuration); + @UserIdInt int userId, UserCase userCase, TimeZoneConfiguration configuration) { + TimeZoneCapabilities capabilities = createCapabilities(userId, userCase, configuration); mFakeCallback.initializeUser(userId, capabilities, configuration); return this; } @@ -989,27 +1321,24 @@ public class TimeZoneDetectorStrategyImplTest { return this; } - Script simulateAutoTimeZoneDetectionEnabled(@UserIdInt int userId, boolean enabled) { - TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder() - .setAutoDetectionEnabled(enabled) - .build(); - return simulateUpdateConfiguration(userId, configuration); - } - /** - * Simulates the time zone detection strategy receiving an updated configuration. + * Simulates the time zone detection strategy receiving an updated configuration and checks + * the return value. */ Script simulateUpdateConfiguration( - @UserIdInt int userId, TimeZoneConfiguration configuration) { - mTimeZoneDetectorStrategy.updateConfiguration(userId, configuration); + @UserIdInt int userId, TimeZoneConfiguration configuration, + boolean expectedResult) { + assertEquals(expectedResult, + mTimeZoneDetectorStrategy.updateConfiguration(userId, configuration)); return this; } /** - * Simulates the time zone detection strategy receiving a telephony-originated suggestion. + * Simulates the time zone detection strategy receiving a geolocation-originated + * suggestion. */ - Script simulateTelephonyTimeZoneSuggestion(TelephonyTimeZoneSuggestion timeZoneSuggestion) { - mTimeZoneDetectorStrategy.suggestTelephonyTimeZone(timeZoneSuggestion); + Script simulateGeolocationTimeZoneSuggestion(GeolocationTimeZoneSuggestion suggestion) { + mTimeZoneDetectorStrategy.suggestGeolocationTimeZone(suggestion); return this; } @@ -1024,13 +1353,26 @@ public class TimeZoneDetectorStrategyImplTest { return this; } + /** + * Simulates the time zone detection strategy receiving a telephony-originated suggestion. + */ + Script simulateTelephonyTimeZoneSuggestion(TelephonyTimeZoneSuggestion timeZoneSuggestion) { + mTimeZoneDetectorStrategy.suggestTelephonyTimeZone(timeZoneSuggestion); + return this; + } + + /** + * Confirms that the device's time zone has not been set by previous actions since the test + * state was last reset. + */ Script verifyTimeZoneNotChanged() { mFakeCallback.assertTimeZoneNotChanged(); return this; } - Script verifyTimeZoneChangedAndReset(TelephonyTimeZoneSuggestion suggestion) { - mFakeCallback.assertTimeZoneChangedTo(suggestion.getZoneId()); + /** Verifies the device's time zone has been set and clears change tracking history. */ + Script verifyTimeZoneChangedAndReset(String zoneId) { + mFakeCallback.assertTimeZoneChangedTo(zoneId); mFakeCallback.commitAllChanges(); return this; } @@ -1041,6 +1383,12 @@ public class TimeZoneDetectorStrategyImplTest { return this; } + Script verifyTimeZoneChangedAndReset(TelephonyTimeZoneSuggestion suggestion) { + mFakeCallback.assertTimeZoneChangedTo(suggestion.getZoneId()); + mFakeCallback.commitAllChanges(); + return this; + } + /** * Verifies that the configuration has been changed to the expected value. */ @@ -1120,4 +1468,8 @@ public class TimeZoneDetectorStrategyImplTest { mOnConfigurationChangedCalled = false; } } + + private static <T> List<T> list(T... values) { + return Arrays.asList(values); + } } diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java deleted file mode 100644 index f6c854e23494..000000000000 --- a/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2018 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.server.slice; - -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.testing.AndroidTestingRunner; -import android.testing.TestableLooper.RunWithLooper; - -import androidx.test.filters.SmallTest; - -import com.android.server.UiServiceTestCase; -import com.android.server.slice.SliceManagerService.PackageMatchingCache; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.function.Supplier; - -@SmallTest -@RunWith(AndroidTestingRunner.class) -@RunWithLooper -public class PackageMatchingCacheTest extends UiServiceTestCase { - - private final Supplier<String> supplier = mock(Supplier.class); - private final PackageMatchingCache cache = new PackageMatchingCache(supplier); - - @Test - public void testNulls() { - // Doesn't get for a null input - cache.matches(null); - verify(supplier, never()).get(); - - // Gets once valid input in sent. - cache.matches(""); - verify(supplier).get(); - } - - @Test - public void testCaching() { - when(supplier.get()).thenReturn("ret.pkg"); - - assertTrue(cache.matches("ret.pkg")); - assertTrue(cache.matches("ret.pkg")); - assertTrue(cache.matches("ret.pkg")); - - verify(supplier, times(1)).get(); - } - - @Test - public void testGetOnFailure() { - when(supplier.get()).thenReturn("ret.pkg"); - assertTrue(cache.matches("ret.pkg")); - - when(supplier.get()).thenReturn("other.pkg"); - assertTrue(cache.matches("other.pkg")); - verify(supplier, times(2)).get(); - } -} diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java index a4436951f48b..cf1c36c0d243 100644 --- a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java @@ -90,8 +90,6 @@ public class SliceManagerServiceTest extends UiServiceTestCase { @Test public void testAddPinCreatesPinned() throws RemoteException { - doReturn("pkg").when(mService).getDefaultHome(anyInt()); - mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken); mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken); verify(mService, times(1)).createPinnedSlice(eq(maybeAddUserId(TEST_URI, 0)), anyString()); @@ -99,8 +97,6 @@ public class SliceManagerServiceTest extends UiServiceTestCase { @Test public void testRemovePinDestroysPinned() throws RemoteException { - doReturn("pkg").when(mService).getDefaultHome(anyInt()); - mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken); when(mCreatedSliceState.unpin(eq("pkg"), eq(mToken))).thenReturn(false); diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp index b3d75d31cb60..4ca5b9e4b14f 100644 --- a/services/tests/wmtests/Android.bp +++ b/services/tests/wmtests/Android.bp @@ -2,15 +2,37 @@ // Build WmTests package //######################################################################## +// Include all test java files. +filegroup { + name: "wmtests-sources", + srcs: [ + "src/**/*.java", + ], +} + +genrule { + name: "wmtests.protologsrc", + srcs: [ + ":protolog-groups", + ":wmtests-sources", + ], + tools: ["protologtool"], + cmd: "$(location protologtool) transform-protolog-calls " + + "--protolog-class com.android.internal.protolog.common.ProtoLog " + + "--protolog-impl-class com.android.internal.protolog.ProtoLogImpl " + + "--protolog-cache-class 'com.android.server.wm.ProtoLogCache' " + + "--loggroups-class com.android.internal.protolog.ProtoLogGroup " + + "--loggroups-jar $(location :protolog-groups) " + + "--output-srcjar $(out) " + + "$(locations :wmtests-sources)", + out: ["wmtests.protolog.srcjar"], +} + android_test { name: "WmTests", // We only want this apk build for tests. - - // Include all test java files. - srcs: [ - "src/**/*.java", - ], + srcs: [":wmtests.protologsrc"], static_libs: [ "frameworks-base-testutils", diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java index 2e988af29638..567610018fc1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java @@ -225,5 +225,27 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase { mockSession.finishMocking(); } + + @Test + public void testResumeNextActivityOnCrashedAppDied() { + mSupervisor.beginDeferResume(); + final ActivityRecord homeActivity = new ActivityBuilder(mAtm) + .setTask(mRootWindowContainer.getDefaultTaskDisplayArea().getOrCreateRootHomeTask()) + .build(); + final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build(); + mSupervisor.endDeferResume(); + // Assume the activity is finishing and hidden because it was crashed. + activity.finishing = true; + activity.mVisibleRequested = false; + activity.setVisible(false); + activity.getRootTask().mPausingActivity = activity; + homeActivity.setState(Task.ActivityState.PAUSED, "test"); + + // Even the visibility states are invisible, the next activity should be resumed because + // the crashed activity was pausing. + mAtm.mInternal.handleAppDied(activity.app, false /* restarting */, + null /* finishInstrumentationCallback */); + assertEquals(Task.ActivityState.RESUMED, homeActivity.getState()); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java b/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java index d1510cf811fb..8223024234fb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java @@ -25,9 +25,12 @@ import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; -import com.android.server.protolog.ProtoLogImpl; +import com.android.internal.protolog.ProtoLogGroup; +import com.android.internal.protolog.ProtoLogImpl; +import com.android.internal.protolog.common.ProtoLog; import org.junit.After; +import org.junit.Ignore; import org.junit.Test; /** @@ -35,6 +38,7 @@ import org.junit.Test; */ @SmallTest @Presubmit +@Ignore("b/163095037") public class ProtoLogIntegrationTest { @After public void tearDown() { @@ -44,17 +48,21 @@ public class ProtoLogIntegrationTest { @Test public void testProtoLogToolIntegration() { ProtoLogImpl mockedProtoLog = mock(ProtoLogImpl.class); - runWith(mockedProtoLog, () -> { - ProtoLogGroup.testProtoLog(); - }); + runWith(mockedProtoLog, this::testProtoLog); verify(mockedProtoLog).log(eq(ProtoLogImpl.LogLevel.ERROR), eq(ProtoLogGroup.TEST_GROUP), anyInt(), eq(0b0010101001010111), - eq(ProtoLogGroup.TEST_GROUP.isLogToLogcat() + eq(com.android.internal.protolog.ProtoLogGroup.TEST_GROUP.isLogToLogcat() ? "Test completed successfully: %b %d %o %x %e %g %f %% %s" : null), eq(new Object[]{true, 1L, 2L, 3L, 0.4, 0.5, 0.6, "ok"})); } + private void testProtoLog() { + ProtoLog.e(ProtoLogGroup.TEST_GROUP, + "Test completed successfully: %b %d %o %x %e %g %f %% %s.", + true, 1, 2, 3, 0.4, 0.5, 0.6, "ok"); + } + /** * Starts protolog for the duration of {@code runnable}, with a ProtoLogImpl instance installed. */ diff --git a/tests/Internal/Android.bp b/tests/Internal/Android.bp index e233fed7e785..9da17db6a573 100644 --- a/tests/Internal/Android.bp +++ b/tests/Internal/Android.bp @@ -11,6 +11,7 @@ android_test { "androidx.test.rules", "mockito-target-minus-junit4", "truth-prebuilt", + "platform-test-annotations", ], java_resource_dirs: ["res"], certificate: "platform", diff --git a/services/tests/servicestests/src/com/android/server/protolog/ProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java index 3e9f625ecdd9..3db011683a86 100644 --- a/services/tests/servicestests/src/com/android/server/protolog/ProtoLogImplTest.java +++ b/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package com.android.server.protolog; +package com.android.internal.protolog; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; -import static com.android.server.protolog.ProtoLogImpl.PROTOLOG_VERSION; +import static com.android.internal.protolog.ProtoLogImpl.PROTOLOG_VERSION; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -42,7 +42,7 @@ import android.util.proto.ProtoInputStream; import androidx.test.filters.SmallTest; -import com.android.server.protolog.common.IProtoLogGroup; +import com.android.internal.protolog.common.IProtoLogGroup; import org.junit.After; import org.junit.Before; diff --git a/services/tests/servicestests/src/com/android/server/protolog/ProtoLogViewerConfigReaderTest.java b/tests/Internal/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java index 02540559fbd0..ae5021638745 100644 --- a/services/tests/servicestests/src/com/android/server/protolog/ProtoLogViewerConfigReaderTest.java +++ b/tests/Internal/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.protolog; +package com.android.internal.protolog; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; diff --git a/services/tests/servicestests/src/com/android/server/protolog/common/LogDataTypeTest.java b/tests/Internal/src/com/android/internal/protolog/common/LogDataTypeTest.java index 4c7f5fdc821c..e20ca3df57c7 100644 --- a/services/tests/servicestests/src/com/android/server/protolog/common/LogDataTypeTest.java +++ b/tests/Internal/src/com/android/internal/protolog/common/LogDataTypeTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.protolog.common; +package com.android.internal.protolog.common; import static org.junit.Assert.assertEquals; diff --git a/tools/protologtool/Android.bp b/tools/protologtool/Android.bp index ce551bd0cc10..0be80d31990a 100644 --- a/tools/protologtool/Android.bp +++ b/tools/protologtool/Android.bp @@ -2,9 +2,9 @@ java_library_host { name: "protologtool-lib", srcs: [ "src/com/android/protolog/tool/**/*.kt", + ":protolog-common-src", ], static_libs: [ - "protolog-common", "javaparser", "platformprotos", "jsonlib", diff --git a/tools/protologtool/src/com/android/protolog/tool/LogParser.kt b/tools/protologtool/src/com/android/protolog/tool/LogParser.kt index a59038fc99a0..645c5672da64 100644 --- a/tools/protologtool/src/com/android/protolog/tool/LogParser.kt +++ b/tools/protologtool/src/com/android/protolog/tool/LogParser.kt @@ -16,16 +16,15 @@ package com.android.protolog.tool +import com.android.internal.protolog.ProtoLogFileProto +import com.android.internal.protolog.ProtoLogMessage +import com.android.internal.protolog.common.InvalidFormatStringException +import com.android.internal.protolog.common.LogDataType import com.android.json.stream.JsonReader -import com.android.server.protolog.common.InvalidFormatStringException -import com.android.server.protolog.common.LogDataType -import com.android.server.protolog.ProtoLogMessage -import com.android.server.protolog.ProtoLogFileProto import java.io.BufferedReader import java.io.InputStream import java.io.InputStreamReader import java.io.PrintStream -import java.lang.Exception import java.text.SimpleDateFormat import java.util.Date import java.util.Locale diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogGroupReader.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogGroupReader.kt index 75493b6427cb..42b628b0e262 100644 --- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogGroupReader.kt +++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogGroupReader.kt @@ -17,7 +17,7 @@ package com.android.protolog.tool import com.android.protolog.tool.Constants.ENUM_VALUES_METHOD -import com.android.server.protolog.common.IProtoLogGroup +import com.android.internal.protolog.common.IProtoLogGroup import java.io.File import java.net.URLClassLoader diff --git a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt index 36ea41129450..27e61a139451 100644 --- a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt +++ b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt @@ -16,7 +16,7 @@ package com.android.protolog.tool -import com.android.server.protolog.common.LogDataType +import com.android.internal.protolog.common.LogDataType import com.github.javaparser.StaticJavaParser import com.github.javaparser.ast.CompilationUnit import com.github.javaparser.ast.NodeList @@ -89,7 +89,7 @@ class SourceTransformer( // Out: ProtoLog.e(GROUP, 1234, 0, null, arg) newCall.arguments.add(2, IntegerLiteralExpr(typeMask)) // Replace call to a stub method with an actual implementation. - // Out: com.android.server.protolog.ProtoLogImpl.e(GROUP, 1234, null, arg) + // Out: ProtoLogImpl.e(GROUP, 1234, null, arg) newCall.setScope(protoLogImplClassNode) // Create a call to ProtoLog$Cache.GROUP_enabled // Out: com.android.server.protolog.ProtoLog$Cache.GROUP_enabled @@ -119,9 +119,9 @@ class SourceTransformer( } blockStmt.addStatement(ExpressionStmt(newCall)) // Create an IF-statement with the previously created condition. - // Out: if (com.android.server.protolog.ProtoLogImpl.isEnabled(GROUP)) { + // Out: if (ProtoLogImpl.isEnabled(GROUP)) { // long protoLogParam0 = arg; - // com.android.server.protolog.ProtoLogImpl.e(GROUP, 1234, 0, null, protoLogParam0); + // ProtoLogImpl.e(GROUP, 1234, 0, null, protoLogParam0); // } ifStmt = IfStmt(isLogEnabled, blockStmt, null) } else { diff --git a/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt b/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt index cf36651c3e39..3cfbb435a764 100644 --- a/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt +++ b/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt @@ -31,7 +31,7 @@ class CommandOptionsTest { private const val TEST_PROTOLOG_CLASS = "com.android.server.wm.ProtoLog" private const val TEST_PROTOLOGIMPL_CLASS = "com.android.server.wm.ProtoLogImpl" private const val TEST_PROTOLOGCACHE_CLASS = "com.android.server.wm.ProtoLog\$Cache" - private const val TEST_PROTOLOGGROUP_CLASS = "com.android.server.wm.ProtoLogGroup" + private const val TEST_PROTOLOGGROUP_CLASS = "com.android.internal.protolog.ProtoLogGroup" private const val TEST_PROTOLOGGROUP_JAR = "out/soong/.intermediates/frameworks/base/" + "services/core/services.core.wm.protologgroups/android_common/javac/" + "services.core.wm.protologgroups.jar" diff --git a/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt b/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt index dd8a0b1c50b4..0d2b91d6cfb8 100644 --- a/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt +++ b/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt @@ -33,8 +33,8 @@ class EndToEndTest { val output = run( src = "frameworks/base/org/example/Example.java" to """ package org.example; - import com.android.server.protolog.common.ProtoLog; - import static com.android.server.wm.ProtoLogGroup.GROUP; + import com.android.internal.protolog.common.ProtoLog; + import static com.android.internal.protolog.ProtoLogGroup.GROUP; class Example { void method() { @@ -46,11 +46,11 @@ class EndToEndTest { """.trimIndent(), logGroup = LogGroup("GROUP", true, false, "TAG_GROUP"), commandOptions = CommandOptions(arrayOf("transform-protolog-calls", - "--protolog-class", "com.android.server.protolog.common.ProtoLog", - "--protolog-impl-class", "com.android.server.protolog.ProtoLogImpl", + "--protolog-class", "com.android.internal.protolog.common.ProtoLog", + "--protolog-impl-class", "com.android.internal.protolog.ProtoLogImpl", "--protolog-cache-class", - "com.android.server.protolog.ProtoLog${"\$\$"}Cache", - "--loggroups-class", "com.android.server.wm.ProtoLogGroup", + "com.android.server.wm.ProtoLogCache", + "--loggroups-class", "com.android.internal.protolog.ProtoLogGroup", "--loggroups-jar", "not_required.jar", "--output-srcjar", "out.srcjar", "frameworks/base/org/example/Example.java")) @@ -64,8 +64,8 @@ class EndToEndTest { val output = run( src = "frameworks/base/org/example/Example.java" to """ package org.example; - import com.android.server.protolog.common.ProtoLog; - import static com.android.server.wm.ProtoLogGroup.GROUP; + import com.android.internal.protolog.common.ProtoLog; + import static com.android.internal.protolog.ProtoLogGroup.GROUP; class Example { void method() { @@ -77,8 +77,8 @@ class EndToEndTest { """.trimIndent(), logGroup = LogGroup("GROUP", true, false, "TAG_GROUP"), commandOptions = CommandOptions(arrayOf("generate-viewer-config", - "--protolog-class", "com.android.server.protolog.common.ProtoLog", - "--loggroups-class", "com.android.server.wm.ProtoLogGroup", + "--protolog-class", "com.android.internal.protolog.common.ProtoLog", + "--loggroups-class", "com.android.internal.protolog.ProtoLogGroup", "--loggroups-jar", "not_required.jar", "--viewer-conf", "out.json", "frameworks/base/org/example/Example.java")) diff --git a/tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt b/tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt index 04a3bfa499d8..67a31da87081 100644 --- a/tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt +++ b/tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt @@ -17,8 +17,8 @@ package com.android.protolog.tool import com.android.json.stream.JsonReader -import com.android.server.protolog.ProtoLogMessage -import com.android.server.protolog.ProtoLogFileProto +import com.android.internal.protolog.ProtoLogMessage +import com.android.internal.protolog.ProtoLogFileProto import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt index 53c69c47d052..eff64a31367a 100644 --- a/wifi/api/system-current.txt +++ b/wifi/api/system-current.txt @@ -326,6 +326,8 @@ package android.net.wifi { field @Deprecated public static final int METERED_OVERRIDE_METERED = 1; // 0x1 field @Deprecated public static final int METERED_OVERRIDE_NONE = 0; // 0x0 field @Deprecated public static final int METERED_OVERRIDE_NOT_METERED = 2; // 0x2 + field @Deprecated public static final int RANDOMIZATION_AUTO = 3; // 0x3 + field @Deprecated public static final int RANDOMIZATION_ENHANCED = 2; // 0x2 field @Deprecated public static final int RANDOMIZATION_NONE = 0; // 0x0 field @Deprecated public static final int RANDOMIZATION_PERSISTENT = 1; // 0x1 field @Deprecated public static final int RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA = 17; // 0x11 diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 71f0ab8087ab..1588bf72c969 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -1130,7 +1130,9 @@ public class WifiConfiguration implements Parcelable { @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"RANDOMIZATION_"}, value = { RANDOMIZATION_NONE, - RANDOMIZATION_PERSISTENT}) + RANDOMIZATION_PERSISTENT, + RANDOMIZATION_ENHANCED, + RANDOMIZATION_AUTO}) public @interface MacRandomizationSetting {} /** @@ -1147,14 +1149,30 @@ public class WifiConfiguration implements Parcelable { public static final int RANDOMIZATION_PERSISTENT = 1; /** + * Use a randomly generated MAC address for connections to this network. + * This option does not persist the randomized MAC address. + * @hide + */ + @SystemApi + public static final int RANDOMIZATION_ENHANCED = 2; + + /** + * Let the wifi framework automatically decide the MAC randomization strategy. + * @hide + */ + @SystemApi + public static final int RANDOMIZATION_AUTO = 3; + + /** * Level of MAC randomization for this network. - * One of {@link #RANDOMIZATION_NONE} or {@link #RANDOMIZATION_PERSISTENT}. - * By default this field is set to {@link #RANDOMIZATION_PERSISTENT}. + * One of {@link #RANDOMIZATION_NONE}, {@link #RANDOMIZATION_AUTO}, + * {@link #RANDOMIZATION_PERSISTENT} or {@link #RANDOMIZATION_ENHANCED}. + * By default this field is set to {@link #RANDOMIZATION_AUTO}. * @hide */ @SystemApi @MacRandomizationSetting - public int macRandomizationSetting = RANDOMIZATION_PERSISTENT; + public int macRandomizationSetting = RANDOMIZATION_AUTO; /** * @hide |