diff options
751 files changed, 11653 insertions, 6599 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java index 876d73a570af..8e26052ee08b 100644 --- a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java +++ b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java @@ -125,10 +125,11 @@ public class AppStateTrackerImpl implements AppStateTracker { private int[] mTempExemptAppIds = mPowerExemptAllAppIds; /** - * Per-user packages that are in the EXEMPT bucket. + * Per-user packages that are in the EXEMPTED bucket. */ @GuardedBy("mLock") - private final SparseSetArray<String> mExemptBucketPackages = new SparseSetArray<>(); + @VisibleForTesting + final SparseSetArray<String> mExemptedBucketPackages = new SparseSetArray<>(); @GuardedBy("mLock") final ArraySet<Listener> mListeners = new ArraySet<>(); @@ -180,7 +181,7 @@ public class AppStateTrackerImpl implements AppStateTracker { int ALL_UNEXEMPTED = 3; int ALL_EXEMPTION_LIST_CHANGED = 4; int TEMP_EXEMPTION_LIST_CHANGED = 5; - int EXEMPT_BUCKET_CHANGED = 6; + int EXEMPTED_BUCKET_CHANGED = 6; int FORCE_ALL_CHANGED = 7; int FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 8; @@ -195,7 +196,7 @@ public class AppStateTrackerImpl implements AppStateTracker { "ALL_UNEXEMPTED", "ALL_EXEMPTION_LIST_CHANGED", "TEMP_EXEMPTION_LIST_CHANGED", - "EXEMPT_BUCKET_CHANGED", + "EXEMPTED_BUCKET_CHANGED", "FORCE_ALL_CHANGED", "FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED", @@ -338,9 +339,9 @@ public class AppStateTrackerImpl implements AppStateTracker { } /** - * This is called when the EXEMPT bucket is updated. + * This is called when the EXEMPTED bucket is updated. */ - private void onExemptBucketChanged(AppStateTrackerImpl sender) { + private void onExemptedBucketChanged(AppStateTrackerImpl sender) { // This doesn't happen very often, so just re-evaluate all jobs / alarms. updateAllJobs(); unblockAllUnrestrictedAlarms(); @@ -424,6 +425,38 @@ public class AppStateTrackerImpl implements AppStateTracker { mHandler = new MyHandler(looper); } + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); + switch (intent.getAction()) { + case Intent.ACTION_USER_REMOVED: + if (userId > 0) { + mHandler.doUserRemoved(userId); + } + break; + case Intent.ACTION_BATTERY_CHANGED: + synchronized (mLock) { + mIsPluggedIn = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0); + } + updateForceAllAppStandbyState(); + break; + case Intent.ACTION_PACKAGE_REMOVED: + if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { + final String pkgName = intent.getData().getSchemeSpecificPart(); + final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); + // No need to notify for state change as all the alarms and jobs should be + // removed too. + mExemptedBucketPackages.remove(userId, pkgName); + mRunAnyRestrictedPackages.remove(Pair.create(uid, pkgName)); + mActiveUids.delete(uid); + mForegroundUids.delete(uid); + } + break; + } + } + }; + /** * Call it when the system is ready. */ @@ -465,8 +498,11 @@ public class AppStateTrackerImpl implements AppStateTracker { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_USER_REMOVED); filter.addAction(Intent.ACTION_BATTERY_CHANGED); - filter.addAction(Intent.ACTION_PACKAGE_REMOVED); - mContext.registerReceiver(new MyReceiver(), filter); + mContext.registerReceiver(mReceiver, filter); + + filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED); + filter.addDataScheme(IntentFilter.SCHEME_PACKAGE); + mContext.registerReceiver(mReceiver, filter); refreshForcedAppStandbyUidPackagesLocked(); @@ -693,30 +729,6 @@ public class AppStateTrackerImpl implements AppStateTracker { } } - private final class MyReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) { - final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); - if (userId > 0) { - mHandler.doUserRemoved(userId); - } - } else if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) { - synchronized (mLock) { - mIsPluggedIn = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0); - } - updateForceAllAppStandbyState(); - } else if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction()) - && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { - final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); - final String pkgName = intent.getData().getSchemeSpecificPart(); - if (mExemptBucketPackages.remove(userId, pkgName)) { - mHandler.notifyExemptBucketChanged(); - } - } - } - } - final class StandbyTracker extends AppIdleStateChangeListener { @Override public void onAppIdleStateChanged(String packageName, int userId, boolean idle, @@ -728,12 +740,12 @@ public class AppStateTrackerImpl implements AppStateTracker { synchronized (mLock) { final boolean changed; if (bucket == UsageStatsManager.STANDBY_BUCKET_EXEMPTED) { - changed = mExemptBucketPackages.add(userId, packageName); + changed = mExemptedBucketPackages.add(userId, packageName); } else { - changed = mExemptBucketPackages.remove(userId, packageName); + changed = mExemptedBucketPackages.remove(userId, packageName); } if (changed) { - mHandler.notifyExemptBucketChanged(); + mHandler.notifyExemptedBucketChanged(); } } } @@ -755,7 +767,7 @@ public class AppStateTrackerImpl implements AppStateTracker { private static final int MSG_FORCE_ALL_CHANGED = 7; private static final int MSG_USER_REMOVED = 8; private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 9; - private static final int MSG_EXEMPT_BUCKET_CHANGED = 10; + private static final int MSG_EXEMPTED_BUCKET_CHANGED = 10; private static final int MSG_ON_UID_STATE_CHANGED = 11; private static final int MSG_ON_UID_ACTIVE = 12; @@ -803,9 +815,9 @@ public class AppStateTrackerImpl implements AppStateTracker { obtainMessage(MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED).sendToTarget(); } - public void notifyExemptBucketChanged() { - removeMessages(MSG_EXEMPT_BUCKET_CHANGED); - obtainMessage(MSG_EXEMPT_BUCKET_CHANGED).sendToTarget(); + public void notifyExemptedBucketChanged() { + removeMessages(MSG_EXEMPTED_BUCKET_CHANGED); + obtainMessage(MSG_EXEMPTED_BUCKET_CHANGED).sendToTarget(); } public void doUserRemoved(int userId) { @@ -888,11 +900,11 @@ public class AppStateTrackerImpl implements AppStateTracker { mStatLogger.logDurationStat(Stats.TEMP_EXEMPTION_LIST_CHANGED, start); return; - case MSG_EXEMPT_BUCKET_CHANGED: + case MSG_EXEMPTED_BUCKET_CHANGED: for (Listener l : cloneListeners()) { - l.onExemptBucketChanged(sender); + l.onExemptedBucketChanged(sender); } - mStatLogger.logDurationStat(Stats.EXEMPT_BUCKET_CHANGED, start); + mStatLogger.logDurationStat(Stats.EXEMPTED_BUCKET_CHANGED, start); return; case MSG_FORCE_ALL_CHANGED: @@ -1005,7 +1017,7 @@ public class AppStateTrackerImpl implements AppStateTracker { } cleanUpArrayForUser(mActiveUids, removedUserId); cleanUpArrayForUser(mForegroundUids, removedUserId); - mExemptBucketPackages.remove(removedUserId); + mExemptedBucketPackages.remove(removedUserId); } } @@ -1148,7 +1160,7 @@ public class AppStateTrackerImpl implements AppStateTracker { } final int userId = UserHandle.getUserId(uid); if (mAppStandbyInternal.isAppIdleEnabled() && !mAppStandbyInternal.isInParole() - && mExemptBucketPackages.contains(userId, packageName)) { + && mExemptedBucketPackages.contains(userId, packageName)) { return false; } return mForceAllAppsStandby; @@ -1301,14 +1313,14 @@ public class AppStateTrackerImpl implements AppStateTracker { pw.println("Exempted bucket packages:"); pw.increaseIndent(); - for (int i = 0; i < mExemptBucketPackages.size(); i++) { + for (int i = 0; i < mExemptedBucketPackages.size(); i++) { pw.print("User "); - pw.print(mExemptBucketPackages.keyAt(i)); + pw.print(mExemptedBucketPackages.keyAt(i)); pw.println(); pw.increaseIndent(); - for (int j = 0; j < mExemptBucketPackages.sizeAt(i); j++) { - pw.print(mExemptBucketPackages.valueAt(i, j)); + for (int j = 0; j < mExemptedBucketPackages.sizeAt(i); j++) { + pw.print(mExemptedBucketPackages.valueAt(i, j)); pw.println(); } pw.decreaseIndent(); @@ -1384,12 +1396,13 @@ public class AppStateTrackerImpl implements AppStateTracker { proto.write(AppStateTrackerProto.TEMP_POWER_SAVE_EXEMPT_APP_IDS, appId); } - for (int i = 0; i < mExemptBucketPackages.size(); i++) { - for (int j = 0; j < mExemptBucketPackages.sizeAt(i); j++) { + for (int i = 0; i < mExemptedBucketPackages.size(); i++) { + for (int j = 0; j < mExemptedBucketPackages.sizeAt(i); j++) { final long token2 = proto.start(AppStateTrackerProto.EXEMPTED_BUCKET_PACKAGES); - proto.write(ExemptedPackage.USER_ID, mExemptBucketPackages.keyAt(i)); - proto.write(ExemptedPackage.PACKAGE_NAME, mExemptBucketPackages.valueAt(i, j)); + proto.write(ExemptedPackage.USER_ID, mExemptedBucketPackages.keyAt(i)); + proto.write(ExemptedPackage.PACKAGE_NAME, + mExemptedBucketPackages.valueAt(i, j)); proto.end(token2); } diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java index 4194fd0068c2..e2f13c560879 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -4310,7 +4310,7 @@ public class AlarmManagerService extends SystemService { filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addAction(Intent.ACTION_PACKAGE_RESTARTED); filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); - filter.addDataScheme("package"); + filter.addDataScheme(IntentFilter.SCHEME_PACKAGE); getContext().registerReceiver(this, filter); // Register for events related to sdcard installation. IntentFilter sdFilter = new IntentFilter(); diff --git a/api/current.txt b/api/current.txt index 532c3d938334..9e0d88ecdfd1 100644 --- a/api/current.txt +++ b/api/current.txt @@ -46987,7 +46987,7 @@ package android.telephony { method public long getNci(); method @IntRange(from=0, to=3279165) public int getNrarfcn(); method @IntRange(from=0, to=1007) public int getPci(); - method @IntRange(from=0, to=65535) public int getTac(); + method @IntRange(from=0, to=16777215) public int getTac(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellIdentityNr> CREATOR; } diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt index b587ea1f3b74..7cd8a628c9fc 100644 --- a/api/module-lib-current.txt +++ b/api/module-lib-current.txt @@ -7,6 +7,7 @@ package android.app { public class NotificationManager { method public boolean hasEnabledNotificationListener(@NonNull String, @NonNull android.os.UserHandle); + field public static final String ACTION_NOTIFICATION_LISTENER_ENABLED_CHANGED = "android.app.action.NOTIFICATION_LISTENER_ENABLED_CHANGED"; } } diff --git a/api/test-current.txt b/api/test-current.txt index 10a367fa9267..a1d1fa781096 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -970,6 +970,7 @@ package android.content.pm { method public boolean isSystemApp(); field public static final int PRIVATE_FLAG_PRIVILEGED = 8; // 0x8 field public int privateFlags; + field public int targetSandboxVersion; } public class LauncherApps { @@ -1017,6 +1018,7 @@ package android.content.pm { field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage"; field public static final String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption"; field public static final int FLAG_PERMISSION_APPLY_RESTRICTION = 16384; // 0x4000 + field public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 32; // 0x20 field public static final int FLAG_PERMISSION_GRANTED_BY_ROLE = 32768; // 0x8000 field public static final int FLAG_PERMISSION_ONE_TIME = 65536; // 0x10000 field public static final int FLAG_PERMISSION_POLICY_FIXED = 4; // 0x4 diff --git a/cmds/incidentd/tests/section_list.cpp b/cmds/incidentd/tests/section_list.cpp index 3a45af028518..60f7fb788837 100644 --- a/cmds/incidentd/tests/section_list.cpp +++ b/cmds/incidentd/tests/section_list.cpp @@ -1,4 +1,4 @@ -// This file is a dummy section_list.cpp used for test only. +// This file is a stub section_list.cpp used for test only. #include "section_list.h" #include "frameworks/base/cmds/incidentd/tests/test_proto.pb.h" diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp index 7c419519a558..88db1d84df8e 100644 --- a/cmds/statsd/Android.bp +++ b/cmds/statsd/Android.bp @@ -73,10 +73,10 @@ cc_defaults { "src/HashableDimensionKey.cpp", "src/logd/LogEvent.cpp", "src/logd/LogEventQueue.cpp", - "src/matchers/CombinationLogMatchingTracker.cpp", + "src/matchers/CombinationAtomMatchingTracker.cpp", "src/matchers/EventMatcherWizard.cpp", "src/matchers/matcher_util.cpp", - "src/matchers/SimpleLogMatchingTracker.cpp", + "src/matchers/SimpleAtomMatchingTracker.cpp", "src/metadata_util.cpp", "src/metrics/CountMetricProducer.cpp", "src/metrics/duration_helper/MaxDurationTracker.cpp", diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.cpp b/cmds/statsd/src/condition/CombinationConditionTracker.cpp index e9875baf58c7..7a1ece94fd3e 100644 --- a/cmds/statsd/src/condition/CombinationConditionTracker.cpp +++ b/cmds/statsd/src/condition/CombinationConditionTracker.cpp @@ -92,8 +92,8 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf mUnSlicedChildren.push_back(childIndex); } mChildren.push_back(childIndex); - mTrackerIndex.insert(childTracker->getLogTrackerIndex().begin(), - childTracker->getLogTrackerIndex().end()); + mTrackerIndex.insert(childTracker->getAtomMatchingTrackerIndex().begin(), + childTracker->getAtomMatchingTrackerIndex().end()); } mUnSlicedPartCondition = evaluateCombinationCondition(mUnSlicedChildren, mLogicalOperation, diff --git a/cmds/statsd/src/condition/ConditionTracker.h b/cmds/statsd/src/condition/ConditionTracker.h index 62736c8160bb..9da1af427e5f 100644 --- a/cmds/statsd/src/condition/ConditionTracker.h +++ b/cmds/statsd/src/condition/ConditionTracker.h @@ -18,7 +18,7 @@ #include "condition/condition_util.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" -#include "matchers/LogMatchingTracker.h" +#include "matchers/AtomMatchingTracker.h" #include "matchers/matcher_util.h" #include <utils/RefBase.h> @@ -60,9 +60,9 @@ public: // evaluate current condition given the new event. // event: the new log event - // eventMatcherValues: the results of the LogMatcherTrackers. LogMatcherTrackers always process - // event before ConditionTrackers, because ConditionTracker depends on - // LogMatchingTrackers. + // eventMatcherValues: the results of the AtomMatchingTrackers. AtomMatchingTrackers always + // process event before ConditionTrackers, because ConditionTracker depends + // on AtomMatchingTrackers. // mAllConditions: the list of all ConditionTracker // conditionCache: the cached non-sliced condition of the ConditionTrackers for this new event. // conditionChanged: the bit map to record whether the condition has changed. @@ -88,8 +88,8 @@ public: const bool isPartialLink, std::vector<ConditionState>& conditionCache) const = 0; - // return the list of LogMatchingTracker index that this ConditionTracker uses. - virtual const std::set<int>& getLogTrackerIndex() const { + // return the list of AtomMatchingTracker index that this ConditionTracker uses. + virtual const std::set<int>& getAtomMatchingTrackerIndex() const { return mTrackerIndex; } @@ -136,7 +136,7 @@ protected: // if it's properly initialized. bool mInitialized; - // the list of LogMatchingTracker index that this ConditionTracker uses. + // the list of AtomMatchingTracker index that this ConditionTracker uses. std::set<int> mTrackerIndex; // This variable is only used for CombinationConditionTrackers. diff --git a/cmds/statsd/src/matchers/LogMatchingTracker.h b/cmds/statsd/src/matchers/AtomMatchingTracker.h index 49a41add4560..5194f9970766 100644 --- a/cmds/statsd/src/matchers/LogMatchingTracker.h +++ b/cmds/statsd/src/matchers/AtomMatchingTracker.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef LOG_MATCHING_TRACKER_H -#define LOG_MATCHING_TRACKER_H +#ifndef ATOM_MATCHING_TRACKER_H +#define ATOM_MATCHING_TRACKER_H #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" #include "logd/LogEvent.h" @@ -31,35 +31,36 @@ namespace android { namespace os { namespace statsd { -class LogMatchingTracker : public virtual RefBase { +class AtomMatchingTracker : public virtual RefBase { public: - LogMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash) + AtomMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash) : mId(id), mIndex(index), mInitialized(false), mProtoHash(protoHash){}; - virtual ~LogMatchingTracker(){}; + virtual ~AtomMatchingTracker(){}; - // Initialize this LogMatchingTracker. - // allLogMatchers: the list of the AtomMatcher proto config. This is needed because we don't - // store the proto object in memory. We only need it during initilization. - // allTrackers: the list of the LogMatchingTracker objects. It's a one-to-one mapping with - // allLogMatchers. This is needed because the initialization is done recursively - // for CombinationLogMatchingTrackers using DFS. + // Initialize this AtomMatchingTracker. + // allAtomMatchers: the list of the AtomMatcher proto config. This is needed because we don't + // store the proto object in memory. We only need it during initilization. + // allAtomMatchingTrackers: the list of the AtomMatchingTracker objects. It's a one-to-one + // mapping with allAtomMatchers. This is needed because the + // initialization is done recursively for + // CombinationAtomMatchingTrackers using DFS. // stack: a bit map to record which matcher has been visited on the stack. This is for detecting // circle dependency. - virtual bool init(const std::vector<AtomMatcher>& allLogMatchers, - const std::vector<sp<LogMatchingTracker>>& allTrackers, + virtual bool init(const std::vector<AtomMatcher>& allAtomMatchers, + const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const std::unordered_map<int64_t, int>& matcherMap, std::vector<bool>& stack) = 0; // Called when a log event comes. // event: the log event. - // allTrackers: the list of all LogMatchingTrackers. This is needed because the log processing - // is done recursively. + // allAtomMatchingTrackers: the list of all AtomMatchingTrackers. This is needed because the log + // processing is done recursively. // matcherResults: The cached results for all matchers for this event. Parent matchers can // directly access the children's matching results if they have been evaluated. // Otherwise, call children matchers' onLogEvent. virtual void onLogEvent(const LogEvent& event, - const std::vector<sp<LogMatchingTracker>>& allTrackers, + const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, std::vector<MatchingState>& matcherResults) = 0; // Get the tagIds that this matcher cares about. The combined collection is stored @@ -81,23 +82,23 @@ protected: // Name of this matching. We don't really need the name, but it makes log message easy to debug. const int64_t mId; - // Index of this LogMatchingTracker in MetricsManager's container. + // Index of this AtomMatchingTracker in MetricsManager's container. const int mIndex; - // Whether this LogMatchingTracker has been properly initialized. + // Whether this AtomMatchingTracker has been properly initialized. bool mInitialized; - // The collection of the event tag ids that this LogMatchingTracker cares. So we can quickly + // The collection of the event tag ids that this AtomMatchingTracker cares. So we can quickly // return kNotMatched when we receive an event with an id not in the list. This is especially - // useful when we have a complex CombinationLogMatcherTracker. + // useful when we have a complex CombinationAtomMatchingTracker. 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(MetricsManagerTest, TestCreateAtomMatchingTrackerSimple); + FRIEND_TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerCombination); FRIEND_TEST(ConfigUpdateTest, TestUpdateMatchers); }; @@ -105,4 +106,4 @@ protected: } // namespace os } // namespace android -#endif // LOG_MATCHING_TRACKER_H +#endif // ATOM_MATCHING_TRACKER_H diff --git a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp b/cmds/statsd/src/matchers/CombinationAtomMatchingTracker.cpp index 60bcc26f0873..19637a449c44 100644 --- a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp +++ b/cmds/statsd/src/matchers/CombinationAtomMatchingTracker.cpp @@ -16,7 +16,8 @@ #include "Log.h" -#include "CombinationLogMatchingTracker.h" +#include "CombinationAtomMatchingTracker.h" + #include "matchers/matcher_util.h" namespace android { @@ -27,18 +28,18 @@ using std::set; using std::unordered_map; using std::vector; -CombinationLogMatchingTracker::CombinationLogMatchingTracker(const int64_t& id, const int index, - const uint64_t protoHash) - : LogMatchingTracker(id, index, protoHash) { +CombinationAtomMatchingTracker::CombinationAtomMatchingTracker(const int64_t& id, const int index, + const uint64_t protoHash) + : AtomMatchingTracker(id, index, protoHash) { } -CombinationLogMatchingTracker::~CombinationLogMatchingTracker() { +CombinationAtomMatchingTracker::~CombinationAtomMatchingTracker() { } -bool CombinationLogMatchingTracker::init(const vector<AtomMatcher>& allLogMatchers, - const vector<sp<LogMatchingTracker>>& allTrackers, - const unordered_map<int64_t, int>& matcherMap, - vector<bool>& stack) { +bool CombinationAtomMatchingTracker::init( + const vector<AtomMatcher>& allAtomMatchers, + const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, + const unordered_map<int64_t, int>& matcherMap, vector<bool>& stack) { if (mInitialized) { return true; } @@ -46,7 +47,7 @@ bool CombinationLogMatchingTracker::init(const vector<AtomMatcher>& allLogMatche // mark this node as visited in the recursion stack. stack[mIndex] = true; - AtomMatcher_Combination matcher = allLogMatchers[mIndex].combination(); + AtomMatcher_Combination matcher = allAtomMatchers[mIndex].combination(); // LogicalOperation is missing in the config if (!matcher.has_operation()) { @@ -74,14 +75,15 @@ bool CombinationLogMatchingTracker::init(const vector<AtomMatcher>& allLogMatche return false; } - if (!allTrackers[childIndex]->init(allLogMatchers, allTrackers, matcherMap, stack)) { + if (!allAtomMatchingTrackers[childIndex]->init(allAtomMatchers, allAtomMatchingTrackers, + matcherMap, stack)) { ALOGW("child matcher init failed %lld", (long long)child); return false; } mChildren.push_back(childIndex); - const set<int>& childTagIds = allTrackers[childIndex]->getAtomIds(); + const set<int>& childTagIds = allAtomMatchingTrackers[childIndex]->getAtomIds(); mAtomIds.insert(childTagIds.begin(), childTagIds.end()); } @@ -91,9 +93,9 @@ bool CombinationLogMatchingTracker::init(const vector<AtomMatcher>& allLogMatche return true; } -void CombinationLogMatchingTracker::onLogEvent(const LogEvent& event, - const vector<sp<LogMatchingTracker>>& allTrackers, - vector<MatchingState>& matcherResults) { +void CombinationAtomMatchingTracker::onLogEvent( + const LogEvent& event, const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, + vector<MatchingState>& matcherResults) { // this event has been processed. if (matcherResults[mIndex] != MatchingState::kNotComputed) { return; @@ -107,8 +109,8 @@ void CombinationLogMatchingTracker::onLogEvent(const LogEvent& event, // evaluate children matchers if they haven't been evaluated. for (const int childIndex : mChildren) { if (matcherResults[childIndex] == MatchingState::kNotComputed) { - const sp<LogMatchingTracker>& child = allTrackers[childIndex]; - child->onLogEvent(event, allTrackers, matcherResults); + const sp<AtomMatchingTracker>& child = allAtomMatchingTrackers[childIndex]; + child->onLogEvent(event, allAtomMatchingTrackers, matcherResults); } } diff --git a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.h b/cmds/statsd/src/matchers/CombinationAtomMatchingTracker.h index 6b8a7fb19cf0..06a4932804f5 100644 --- a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.h +++ b/cmds/statsd/src/matchers/CombinationAtomMatchingTracker.h @@ -13,12 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef COMBINATION_LOG_MATCHING_TRACKER_H -#define COMBINATION_LOG_MATCHING_TRACKER_H +#ifndef COMBINATION_ATOM_MATCHING_TRACKER_H +#define COMBINATION_ATOM_MATCHING_TRACKER_H #include <unordered_map> #include <vector> -#include "LogMatchingTracker.h" + +#include "AtomMatchingTracker.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" namespace android { @@ -26,19 +27,18 @@ namespace os { namespace statsd { // Represents a AtomMatcher_Combination in the StatsdConfig. -class CombinationLogMatchingTracker : public virtual LogMatchingTracker { +class CombinationAtomMatchingTracker : public virtual AtomMatchingTracker { public: - CombinationLogMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash); + CombinationAtomMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash); - bool init(const std::vector<AtomMatcher>& allLogMatchers, - const std::vector<sp<LogMatchingTracker>>& allTrackers, - const std::unordered_map<int64_t, int>& matcherMap, - std::vector<bool>& stack); + bool init(const std::vector<AtomMatcher>& allAtomMatchers, + const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, + const std::unordered_map<int64_t, int>& matcherMap, std::vector<bool>& stack); - ~CombinationLogMatchingTracker(); + ~CombinationAtomMatchingTracker(); void onLogEvent(const LogEvent& event, - const std::vector<sp<LogMatchingTracker>>& allTrackers, + const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, std::vector<MatchingState>& matcherResults) override; private: @@ -50,4 +50,4 @@ private: } // namespace statsd } // namespace os } // namespace android -#endif // COMBINATION_LOG_MATCHING_TRACKER_H +#endif // COMBINATION_ATOM_MATCHING_TRACKER_H diff --git a/cmds/statsd/src/matchers/EventMatcherWizard.h b/cmds/statsd/src/matchers/EventMatcherWizard.h index 57ec2b35ba32..5d780f2423d8 100644 --- a/cmds/statsd/src/matchers/EventMatcherWizard.h +++ b/cmds/statsd/src/matchers/EventMatcherWizard.h @@ -16,7 +16,7 @@ #pragma once -#include "LogMatchingTracker.h" +#include "AtomMatchingTracker.h" namespace android { namespace os { @@ -25,7 +25,7 @@ namespace statsd { class EventMatcherWizard : public virtual android::RefBase { public: EventMatcherWizard(){}; // for testing - EventMatcherWizard(const std::vector<sp<LogMatchingTracker>>& eventTrackers) + EventMatcherWizard(const std::vector<sp<AtomMatchingTracker>>& eventTrackers) : mAllEventMatchers(eventTrackers){}; virtual ~EventMatcherWizard(){}; @@ -33,7 +33,7 @@ public: MatchingState matchLogEvent(const LogEvent& event, int matcher_index); private: - std::vector<sp<LogMatchingTracker>> mAllEventMatchers; + std::vector<sp<AtomMatchingTracker>> mAllEventMatchers; }; } // namespace statsd diff --git a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp b/cmds/statsd/src/matchers/SimpleAtomMatchingTracker.cpp index ff47d35b36cc..86b148dd8657 100644 --- a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp +++ b/cmds/statsd/src/matchers/SimpleAtomMatchingTracker.cpp @@ -17,7 +17,7 @@ #define DEBUG false // STOPSHIP if true #include "Log.h" -#include "SimpleLogMatchingTracker.h" +#include "SimpleAtomMatchingTracker.h" namespace android { namespace os { @@ -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 sp<UidMap>& uidMap) - : LogMatchingTracker(id, index, protoHash), mMatcher(matcher), mUidMap(uidMap) { +SimpleAtomMatchingTracker::SimpleAtomMatchingTracker(const int64_t& id, const int index, + const uint64_t protoHash, + const SimpleAtomMatcher& matcher, + const sp<UidMap>& uidMap) + : AtomMatchingTracker(id, index, protoHash), mMatcher(matcher), mUidMap(uidMap) { if (!matcher.has_atom_id()) { mInitialized = false; } else { @@ -39,20 +39,20 @@ SimpleLogMatchingTracker::SimpleLogMatchingTracker(const int64_t& id, const int } } -SimpleLogMatchingTracker::~SimpleLogMatchingTracker() { +SimpleAtomMatchingTracker::~SimpleAtomMatchingTracker() { } -bool SimpleLogMatchingTracker::init(const vector<AtomMatcher>& allLogMatchers, - const vector<sp<LogMatchingTracker>>& allTrackers, - const unordered_map<int64_t, int>& matcherMap, - vector<bool>& stack) { +bool SimpleAtomMatchingTracker::init(const vector<AtomMatcher>& allAtomMatchers, + const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, + const unordered_map<int64_t, int>& matcherMap, + vector<bool>& stack) { // no need to do anything. return mInitialized; } -void SimpleLogMatchingTracker::onLogEvent(const LogEvent& event, - const vector<sp<LogMatchingTracker>>& allTrackers, - vector<MatchingState>& matcherResults) { +void SimpleAtomMatchingTracker::onLogEvent( + const LogEvent& event, const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, + vector<MatchingState>& matcherResults) { if (matcherResults[mIndex] != MatchingState::kNotComputed) { VLOG("Matcher %lld already evaluated ", (long long)mId); return; @@ -65,7 +65,7 @@ void SimpleLogMatchingTracker::onLogEvent(const LogEvent& event, bool matched = matchesSimple(mUidMap, mMatcher, event); matcherResults[mIndex] = matched ? MatchingState::kMatched : MatchingState::kNotMatched; - VLOG("Stats SimpleLogMatcher %lld matched? %d", (long long)mId, matched); + VLOG("Stats SimpleAtomMatcher %lld matched? %d", (long long)mId, matched); } } // namespace statsd diff --git a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.h b/cmds/statsd/src/matchers/SimpleAtomMatchingTracker.h index e58e01252ade..49cbe09f8482 100644 --- a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.h +++ b/cmds/statsd/src/matchers/SimpleAtomMatchingTracker.h @@ -14,12 +14,13 @@ * limitations under the License. */ -#ifndef SIMPLE_LOG_MATCHING_TRACKER_H -#define SIMPLE_LOG_MATCHING_TRACKER_H +#ifndef SIMPLE_ATOM_MATCHING_TRACKER_H +#define SIMPLE_ATOM_MATCHING_TRACKER_H #include <unordered_map> #include <vector> -#include "LogMatchingTracker.h" + +#include "AtomMatchingTracker.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" #include "packages/UidMap.h" @@ -27,20 +28,20 @@ namespace android { namespace os { namespace statsd { -class SimpleLogMatchingTracker : public virtual LogMatchingTracker { +class SimpleAtomMatchingTracker : public virtual AtomMatchingTracker { public: - SimpleLogMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash, - const SimpleAtomMatcher& matcher, const sp<UidMap>& uidMap); + SimpleAtomMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash, + const SimpleAtomMatcher& matcher, const sp<UidMap>& uidMap); - ~SimpleLogMatchingTracker(); + ~SimpleAtomMatchingTracker(); - bool init(const std::vector<AtomMatcher>& allLogMatchers, - const std::vector<sp<LogMatchingTracker>>& allTrackers, + bool init(const std::vector<AtomMatcher>& allAtomMatchers, + const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const std::unordered_map<int64_t, int>& matcherMap, std::vector<bool>& stack) override; void onLogEvent(const LogEvent& event, - const std::vector<sp<LogMatchingTracker>>& allTrackers, + const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, std::vector<MatchingState>& matcherResults) override; private: @@ -51,4 +52,4 @@ private: } // namespace statsd } // namespace os } // namespace android -#endif // SIMPLE_LOG_MATCHING_TRACKER_H +#endif // SIMPLE_ATOM_MATCHING_TRACKER_H diff --git a/cmds/statsd/src/matchers/matcher_util.cpp b/cmds/statsd/src/matchers/matcher_util.cpp index e6d91223308d..a7454c5d923b 100644 --- a/cmds/statsd/src/matchers/matcher_util.cpp +++ b/cmds/statsd/src/matchers/matcher_util.cpp @@ -17,7 +17,7 @@ #include "Log.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" -#include "matchers/LogMatchingTracker.h" +#include "matchers/AtomMatchingTracker.h" #include "matchers/matcher_util.h" #include "stats_util.h" diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h index 2fc772b6b641..ef3a24a43dcc 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.h +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h @@ -170,14 +170,14 @@ private: // for each slice with the latest value. void updateCurrentSlicedBucketForAnomaly(); - // Whitelist of fields to report. Empty means all are reported. + // Allowlist of fields to report. Empty means all are reported. std::vector<Matcher> mFieldMatchers; GaugeMetric::SamplingType mSamplingType; const int64_t mMaxPullDelayNs; - // apply a whitelist on the original input + // apply an allowlist on the original input std::shared_ptr<vector<FieldValue>> getGaugeFields(const LogEvent& event); // Util function to check whether the specified dimension hits the guardrail. diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp index 2c3deca40fa0..5a520326116a 100644 --- a/cmds/statsd/src/metrics/MetricsManager.cpp +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -24,8 +24,8 @@ #include "condition/CombinationConditionTracker.h" #include "condition/SimpleConditionTracker.h" #include "guardrail/StatsdStats.h" -#include "matchers/CombinationLogMatchingTracker.h" -#include "matchers/SimpleLogMatchingTracker.h" +#include "matchers/CombinationAtomMatchingTracker.h" +#include "matchers/SimpleAtomMatchingTracker.h" #include "parsing_utils/config_update_utils.h" #include "parsing_utils/metrics_manager_util.h" #include "state/StateManager.h" @@ -77,14 +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, mLogTrackerMap, mAllConditionTrackers, - mAllMetricProducers, mAllAnomalyTrackers, mAllPeriodicAlarmTrackers, - mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap, - mActivationAtomTrackerToMetricMap, mDeactivationAtomTrackerToMetricMap, - mAlertTrackerMap, mMetricIndexesWithActivation, mNoReportMetricIds); + mConfigValid = initStatsdConfig( + key, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, + timeBaseNs, currentTimeNs, mTagIds, mAllAtomMatchingTrackers, mAtomMatchingTrackerMap, + 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(); @@ -93,7 +93,7 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config, // Init allowed pushed atom uids. if (config.allowed_log_source_size() == 0) { mConfigValid = false; - ALOGE("Log source whitelist is empty! This config won't get any data. Suggest adding at " + ALOGE("Log source allowlist is empty! This config won't get any data. Suggest adding at " "least AID_SYSTEM and AID_STATSD to the allowed_log_source field."); } else { for (const auto& source : config.allowed_log_source()) { @@ -155,7 +155,7 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config, // Guardrail. Reject the config if it's too big. if (mAllMetricProducers.size() > StatsdStats::kMaxMetricCountPerConfig || mAllConditionTrackers.size() > StatsdStats::kMaxConditionCountPerConfig || - mAllAtomMatchers.size() > StatsdStats::kMaxMatcherCountPerConfig) { + mAllAtomMatchingTrackers.size() > StatsdStats::kMaxMatcherCountPerConfig) { ALOGE("This config is too big! Reject!"); mConfigValid = false; } @@ -175,8 +175,9 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config, // no matter whether this config is valid, log it in the stats. StatsdStats::getInstance().noteConfigReceived( - key, mAllMetricProducers.size(), mAllConditionTrackers.size(), mAllAtomMatchers.size(), - mAllAnomalyTrackers.size(), mAnnotations, mConfigValid); + key, mAllMetricProducers.size(), mAllConditionTrackers.size(), + mAllAtomMatchingTrackers.size(), mAllAnomalyTrackers.size(), mAnnotations, + mConfigValid); // Check active for (const auto& metric : mAllMetricProducers) { if (metric->isActive()) { @@ -201,15 +202,15 @@ bool MetricsManager::updateConfig(const StatsdConfig& config, const int64_t time const int64_t currentTimeNs, const sp<AlarmMonitor>& anomalyAlarmMonitor, const sp<AlarmMonitor>& periodicAlarmMonitor) { - vector<sp<LogMatchingTracker>> newAtomMatchers; - unordered_map<int64_t, int> newLogTrackerMap; + vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers; + unordered_map<int64_t, int> newAtomMatchingTrackerMap; mTagIds.clear(); - mConfigValid = - updateStatsdConfig(mConfigKey, config, mUidMap, mPullerManager, anomalyAlarmMonitor, - periodicAlarmMonitor, timeBaseNs, currentTimeNs, mAllAtomMatchers, - mLogTrackerMap, mTagIds, newAtomMatchers, newLogTrackerMap); - mAllAtomMatchers = newAtomMatchers; - mLogTrackerMap = newLogTrackerMap; + mConfigValid = updateStatsdConfig( + mConfigKey, config, mUidMap, mPullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, + timeBaseNs, currentTimeNs, mAllAtomMatchingTrackers, mAtomMatchingTrackerMap, mTagIds, + newAtomMatchingTrackers, newAtomMatchingTrackerMap); + mAllAtomMatchingTrackers = newAtomMatchingTrackers; + mAtomMatchingTrackerMap = newAtomMatchingTrackerMap; return mConfigValid; } @@ -502,11 +503,12 @@ void MetricsManager::onLogEvent(const LogEvent& event) { return; } - vector<MatchingState> matcherCache(mAllAtomMatchers.size(), MatchingState::kNotComputed); + vector<MatchingState> matcherCache(mAllAtomMatchingTrackers.size(), + MatchingState::kNotComputed); // Evaluate all atom matchers. - for (auto& matcher : mAllAtomMatchers) { - matcher->onLogEvent(event, mAllAtomMatchers, matcherCache); + for (auto& matcher : mAllAtomMatchingTrackers) { + matcher->onLogEvent(event, mAllAtomMatchingTrackers, matcherCache); } // Set of metrics that received an activation cancellation. @@ -596,10 +598,10 @@ void MetricsManager::onLogEvent(const LogEvent& event) { } // For matched AtomMatchers, tell relevant metrics that a matched event has come. - for (size_t i = 0; i < mAllAtomMatchers.size(); i++) { + for (size_t i = 0; i < mAllAtomMatchingTrackers.size(); i++) { if (matcherCache[i] == MatchingState::kMatched) { StatsdStats::getInstance().noteMatcherMatched(mConfigKey, - mAllAtomMatchers[i]->getId()); + mAllAtomMatchingTrackers[i]->getId()); auto pair = mTrackerToMetricMap.find(i); if (pair != mTrackerToMetricMap.end()) { auto& metricList = pair->second; diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h index 6f9a23362033..6f4b2d7e9fa4 100644 --- a/cmds/statsd/src/metrics/MetricsManager.h +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -25,7 +25,7 @@ #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" #include "frameworks/base/cmds/statsd/src/statsd_metadata.pb.h" #include "logd/LogEvent.h" -#include "matchers/LogMatchingTracker.h" +#include "matchers/AtomMatchingTracker.h" #include "metrics/MetricProducer.h" #include "packages/UidMap.h" @@ -217,7 +217,7 @@ private: // All event tags that are interesting to my metrics. std::set<int> mTagIds; - // We only store the sp of LogMatchingTracker, MetricProducer, and ConditionTracker in + // We only store the sp of AtomMatchingTracker, MetricProducer, and ConditionTracker in // MetricsManager. There are relationships between them, and the relationships are denoted by // index instead of pointers. The reasons for this are: (1) the relationship between them are // complicated, so storing index instead of pointers reduces the risk that A holds B's sp, and B @@ -225,7 +225,7 @@ private: // the related results from a cache using the index. // Hold all the atom matchers from the config. - std::vector<sp<LogMatchingTracker>> mAllAtomMatchers; + std::vector<sp<AtomMatchingTracker>> mAllAtomMatchingTrackers; // Hold all the conditions from the config. std::vector<sp<ConditionTracker>> mAllConditionTrackers; @@ -239,29 +239,29 @@ 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 + // To make updating configs faster, we map the id of a AtomMatchingTracker, 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; + // Maps the id of an atom matcher to its index in mAllAtomMatchingTrackers. + std::unordered_map<int64_t, int> mAtomMatchingTrackerMap; // 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. // 1st filter: check if the event tag id is in mTagIds. // 2nd filter: if it is, we parse the event because there is at least one member is interested. - // then pass to all LogMatchingTrackers (itself also filter events by ids). - // 3nd filter: for LogMatchingTrackers that matched this event, we pass this event to the + // then pass to all AtomMatchingTrackers (itself also filter events by ids). + // 3nd filter: for AtomMatchingTrackers that matched this event, we pass this event to the // ConditionTrackers and MetricProducers that use this matcher. // 4th filter: for ConditionTrackers that changed value due to this event, we pass // new conditions to metrics that use this condition. // The following map is initialized from the statsd_config. - // Maps from the index of the LogMatchingTracker to index of MetricProducer. + // Maps from the index of the AtomMatchingTracker to index of MetricProducer. std::unordered_map<int, std::vector<int>> mTrackerToMetricMap; - // Maps from LogMatchingTracker to ConditionTracker + // Maps from AtomMatchingTracker to ConditionTracker std::unordered_map<int, std::vector<int>> mTrackerToConditionMap; // Maps from ConditionTracker to MetricProducer diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp index 562e29124187..a9ae5a4e854d 100644 --- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp +++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp @@ -29,9 +29,9 @@ 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, + const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, + const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers, + const unordered_map<int64_t, int>& newAtomMatchingTrackerMap, vector<UpdateStatus>& matchersToUpdate, vector<bool>& cycleTracker) { // Have already examined this matcher. @@ -42,8 +42,8 @@ bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherI 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()) { + const auto& oldAtomMatchingTrackerIt = oldAtomMatchingTrackerMap.find(id); + if (oldAtomMatchingTrackerIt == oldAtomMatchingTrackerMap.end()) { matchersToUpdate[matcherIdx] = UPDATE_REPLACE; return true; } @@ -55,7 +55,7 @@ bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherI return false; } uint64_t newProtoHash = Hash64(serializedMatcher); - if (newProtoHash != oldAtomMatchers[oldLogTrackerIt->second]->getProtoHash()) { + if (newProtoHash != oldAtomMatchingTrackers[oldAtomMatchingTrackerIt->second]->getProtoHash()) { matchersToUpdate[matcherIdx] = UPDATE_REPLACE; return true; } @@ -70,8 +70,8 @@ bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherI 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()) { + const auto& childIt = newAtomMatchingTrackerMap.find(childMatcherId); + if (childIt == newAtomMatchingTrackerMap.end()) { ALOGW("Matcher %lld not found in the config", (long long)childMatcherId); return false; } @@ -80,9 +80,9 @@ bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherI ALOGE("Cycle detected in matcher config"); return false; } - if (!determineMatcherUpdateStatus(config, childIdx, oldLogTrackerMap, - oldAtomMatchers, newLogTrackerMap, - matchersToUpdate, cycleTracker)) { + if (!determineMatcherUpdateStatus( + config, childIdx, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers, + newAtomMatchingTrackerMap, matchersToUpdate, cycleTracker)) { return false; } @@ -103,25 +103,25 @@ bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherI 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) { +bool updateAtomTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap, + const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, + const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers, + set<int>& allTagIds, unordered_map<int64_t, int>& newAtomMatchingTrackerMap, + vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers) { const int atomMatcherCount = config.atom_matcher_size(); vector<AtomMatcher> matcherProtos; matcherProtos.reserve(atomMatcherCount); - newAtomMatchers.reserve(atomMatcherCount); + newAtomMatchingTrackers.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()) { + if (newAtomMatchingTrackerMap.find(matcher.id()) != newAtomMatchingTrackerMap.end()) { ALOGE("Duplicate atom matcher found for id %lld", (long long)matcher.id()); return false; } - newLogTrackerMap[matcher.id()] = i; + newAtomMatchingTrackerMap[matcher.id()] = i; matcherProtos.push_back(matcher); } @@ -129,8 +129,9 @@ bool updateLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap, 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)) { + if (!determineMatcherUpdateStatus(config, i, oldAtomMatchingTrackerMap, + oldAtomMatchingTrackers, newAtomMatchingTrackerMap, + matchersToUpdate, cycleTracker)) { return false; } } @@ -140,23 +141,23 @@ bool updateLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap, const int64_t id = matcher.id(); switch (matchersToUpdate[i]) { case UPDATE_PRESERVE: { - const auto& oldLogTrackerIt = oldLogTrackerMap.find(id); - if (oldLogTrackerIt == oldLogTrackerMap.end()) { + const auto& oldAtomMatchingTrackerIt = oldAtomMatchingTrackerMap.find(id); + if (oldAtomMatchingTrackerIt == oldAtomMatchingTrackerMap.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]); + const int oldIndex = oldAtomMatchingTrackerIt->second; + newAtomMatchingTrackers.push_back(oldAtomMatchingTrackers[oldIndex]); break; } case UPDATE_REPLACE: { - sp<LogMatchingTracker> tracker = createLogTracker(matcher, i, uidMap); + sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(matcher, i, uidMap); if (tracker == nullptr) { return false; } - newAtomMatchers.push_back(tracker); + newAtomMatchingTrackers.push_back(tracker); break; } default: { @@ -168,8 +169,9 @@ bool updateLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap, } std::fill(cycleTracker.begin(), cycleTracker.end(), false); - for (auto& matcher : newAtomMatchers) { - if (!matcher->init(matcherProtos, newAtomMatchers, newLogTrackerMap, cycleTracker)) { + for (auto& matcher : newAtomMatchingTrackers) { + if (!matcher->init(matcherProtos, newAtomMatchingTrackers, newAtomMatchingTrackerMap, + cycleTracker)) { return false; } // Collect all the tag ids that are interesting. TagIds exist in leaf nodes only. @@ -185,13 +187,14 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const 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"); + const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers, + const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, + set<int>& allTagIds, + vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers, + unordered_map<int64_t, int>& newAtomMatchingTrackerMap) { + if (!updateAtomTrackers(config, uidMap, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers, + allTagIds, newAtomMatchingTrackerMap, newAtomMatchingTrackers)) { + ALOGE("updateAtomMatchingTrackers failed"); return false; } @@ -200,4 +203,4 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const } // namespace statsd } // namespace os -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h index 951ab03cee47..ae7b2162e034 100644 --- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h +++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h @@ -20,7 +20,7 @@ #include "anomaly/AlarmMonitor.h" #include "external/StatsPullerManager.h" -#include "matchers/LogMatchingTracker.h" +#include "matchers/AtomMatchingTracker.h" namespace android { namespace os { @@ -42,34 +42,34 @@ enum UpdateStatus { // 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 +// [newAtomMatchingTrackerMap]: matcher id to index mapping in the input StatsdConfig +// [oldAtomMatchingTrackerMap]: matcher id to index mapping in the existing MetricsManager +// [oldAtomMatchingTrackers]: stores the existing AtomMatchingTrackers // 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, + const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, + const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers, + const unordered_map<int64_t, int>& newAtomMatchingTrackerMap, vector<UpdateStatus>& matchersToUpdate, vector<bool>& cycleTracker); -// Updates the LogMatchingTrackers. +// Updates the AtomMatchingTrackers. // input: // [config]: the input StatsdConfig -// [oldLogTrackerMap]: existing matcher id to index mapping -// [oldAtomMatchers]: stores the existing LogMatchingTrackers +// [oldAtomMatchingTrackerMap]: existing matcher id to index mapping +// [oldAtomMatchingTrackers]: stores the existing AtomMatchingTrackers // 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); +// [newAtomMatchingTrackerMap]: new matcher id to index mapping +// [newAtomMatchers]: stores the new AtomMatchingTrackers +bool updateAtomTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap, + const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, + const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers, + set<int>& allTagIds, unordered_map<int64_t, int>& newAtomMatchingTrackerMap, + vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers); // Updates the existing MetricsManager from a new StatsdConfig. // Parameters are the members of MetricsManager. See MetricsManager for declaration. @@ -78,12 +78,12 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const 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, + const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers, + const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, std::set<int>& allTagIds, - std::vector<sp<LogMatchingTracker>>& newAtomMatchers, - unordered_map<int64_t, int>& newLogTrackerMap); + std::vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers, + unordered_map<int64_t, int>& newAtomMatchingTrackerMap); } // namespace statsd } // namespace os -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp index 9d3943fe8260..daf67e93557c 100644 --- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp +++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp @@ -26,9 +26,9 @@ #include "condition/SimpleConditionTracker.h" #include "external/StatsPullerManager.h" #include "hash.h" -#include "matchers/CombinationLogMatchingTracker.h" +#include "matchers/CombinationAtomMatchingTracker.h" #include "matchers/EventMatcherWizard.h" -#include "matchers/SimpleLogMatchingTracker.h" +#include "matchers/SimpleAtomMatchingTracker.h" #include "metrics/CountMetricProducer.h" #include "metrics/DurationMetricProducer.h" #include "metrics/EventMetricProducer.h" @@ -62,8 +62,8 @@ bool hasLeafNode(const FieldMatcher& matcher) { } // namespace -sp<LogMatchingTracker> createLogTracker(const AtomMatcher& logMatcher, const int index, - const sp<UidMap>& uidMap) { +sp<AtomMatchingTracker> createAtomMatchingTracker(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()); @@ -72,11 +72,11 @@ sp<LogMatchingTracker> createLogTracker(const AtomMatcher& logMatcher, const int 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); + return new SimpleAtomMatchingTracker(logMatcher.id(), index, protoHash, + logMatcher.simple_atom_matcher(), uidMap); break; case AtomMatcher::ContentsCase::kCombination: - return new CombinationLogMatchingTracker(logMatcher.id(), index, protoHash); + return new CombinationAtomMatchingTracker(logMatcher.id(), index, protoHash); break; default: ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id()); @@ -84,18 +84,18 @@ sp<LogMatchingTracker> createLogTracker(const AtomMatcher& logMatcher, const int } } -bool handleMetricWithLogTrackers(const int64_t what, const int metricIndex, - const bool usedForDimension, - const vector<sp<LogMatchingTracker>>& allAtomMatchers, - const unordered_map<int64_t, int>& logTrackerMap, - unordered_map<int, std::vector<int>>& trackerToMetricMap, - int& logTrackerIndex) { - auto logTrackerIt = logTrackerMap.find(what); - if (logTrackerIt == logTrackerMap.end()) { +bool handleMetricWithAtomMatchingTrackers( + const int64_t what, const int metricIndex, const bool usedForDimension, + const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, + const unordered_map<int64_t, int>& atomMatchingTrackerMap, + unordered_map<int, std::vector<int>>& trackerToMetricMap, int& logTrackerIndex) { + auto logTrackerIt = atomMatchingTrackerMap.find(what); + if (logTrackerIt == atomMatchingTrackerMap.end()) { ALOGW("cannot find the AtomMatcher \"%lld\" in config", (long long)what); return false; } - if (usedForDimension && allAtomMatchers[logTrackerIt->second]->getAtomIds().size() > 1) { + if (usedForDimension && + allAtomMatchingTrackers[logTrackerIt->second]->getAtomIds().size() > 1) { ALOGE("AtomMatcher \"%lld\" has more than one tag ids. When a metric has dimension, " "the \"what\" can only about one atom type.", (long long)what); @@ -107,17 +107,17 @@ bool handleMetricWithLogTrackers(const int64_t what, const int metricIndex, return true; } -bool handlePullMetricTriggerWithLogTrackers( +bool handlePullMetricTriggerWithAtomMatchingTrackers( const int64_t trigger, const int metricIndex, - const vector<sp<LogMatchingTracker>>& allAtomMatchers, - const unordered_map<int64_t, int>& logTrackerMap, + const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, + const unordered_map<int64_t, int>& atomMatchingTrackerMap, unordered_map<int, std::vector<int>>& trackerToMetricMap, int& logTrackerIndex) { - auto logTrackerIt = logTrackerMap.find(trigger); - if (logTrackerIt == logTrackerMap.end()) { + auto logTrackerIt = atomMatchingTrackerMap.find(trigger); + if (logTrackerIt == atomMatchingTrackerMap.end()) { ALOGW("cannot find the AtomMatcher \"%lld\" in config", (long long)trigger); return false; } - if (allAtomMatchers[logTrackerIt->second]->getAtomIds().size() > 1) { + if (allAtomMatchingTrackers[logTrackerIt->second]->getAtomIds().size() > 1) { ALOGE("AtomMatcher \"%lld\" has more than one tag ids." "Trigger can only be one atom type.", (long long)trigger); @@ -207,7 +207,7 @@ bool handleMetricWithStateLink(const FieldMatcher& stateMatcher, bool handleMetricActivation( const StatsdConfig& config, const int64_t metricId, const int metricIndex, const unordered_map<int64_t, int>& metricToActivationMap, - const unordered_map<int64_t, int>& logTrackerMap, + const unordered_map<int64_t, int>& atomMatchingTrackerMap, unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap, unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap, vector<int>& metricsWithActivation, @@ -223,8 +223,8 @@ bool handleMetricActivation( for (int i = 0; i < metricActivation.event_activation_size(); i++) { const EventActivation& activation = metricActivation.event_activation(i); - auto itr = logTrackerMap.find(activation.atom_matcher_id()); - if (itr == logTrackerMap.end()) { + auto itr = atomMatchingTrackerMap.find(activation.atom_matcher_id()); + if (itr == atomMatchingTrackerMap.end()) { ALOGE("Atom matcher not found for event activation."); return false; } @@ -240,8 +240,8 @@ bool handleMetricActivation( eventActivationMap.emplace(atomMatcherIndex, activationWrapper); if (activation.has_deactivation_atom_matcher_id()) { - itr = logTrackerMap.find(activation.deactivation_atom_matcher_id()); - if (itr == logTrackerMap.end()) { + itr = atomMatchingTrackerMap.find(activation.deactivation_atom_matcher_id()); + if (itr == atomMatchingTrackerMap.end()) { ALOGE("Atom matcher not found for event deactivation."); return false; } @@ -255,33 +255,35 @@ bool handleMetricActivation( return true; } -bool initLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap, - unordered_map<int64_t, int>& logTrackerMap, - vector<sp<LogMatchingTracker>>& allAtomMatchers, set<int>& allTagIds) { +bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap, + unordered_map<int64_t, int>& atomMatchingTrackerMap, + vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, + set<int>& allTagIds) { vector<AtomMatcher> matcherConfigs; const int atomMatcherCount = config.atom_matcher_size(); matcherConfigs.reserve(atomMatcherCount); - allAtomMatchers.reserve(atomMatcherCount); + allAtomMatchingTrackers.reserve(atomMatcherCount); for (int i = 0; i < atomMatcherCount; i++) { const AtomMatcher& logMatcher = config.atom_matcher(i); - int index = allAtomMatchers.size(); - sp<LogMatchingTracker> tracker = createLogTracker(logMatcher, index, uidMap); + int index = allAtomMatchingTrackers.size(); + sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(logMatcher, index, uidMap); if (tracker == nullptr) { return false; } - allAtomMatchers.push_back(tracker); - if (logTrackerMap.find(logMatcher.id()) != logTrackerMap.end()) { + allAtomMatchingTrackers.push_back(tracker); + if (atomMatchingTrackerMap.find(logMatcher.id()) != atomMatchingTrackerMap.end()) { ALOGE("Duplicate AtomMatcher found!"); return false; } - logTrackerMap[logMatcher.id()] = index; + atomMatchingTrackerMap[logMatcher.id()] = index; matcherConfigs.push_back(logMatcher); } - vector<bool> stackTracker2(allAtomMatchers.size(), false); - for (auto& matcher : allAtomMatchers) { - if (!matcher->init(matcherConfigs, allAtomMatchers, logTrackerMap, stackTracker2)) { + vector<bool> stackTracker2(allAtomMatchingTrackers.size(), false); + for (auto& matcher : allAtomMatchingTrackers) { + if (!matcher->init(matcherConfigs, allAtomMatchingTrackers, atomMatchingTrackerMap, + stackTracker2)) { return false; } // Collect all the tag ids that are interesting. TagIds exist in leaf nodes only. @@ -292,7 +294,7 @@ bool initLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap, } bool initConditions(const ConfigKey& key, const StatsdConfig& config, - const unordered_map<int64_t, int>& logTrackerMap, + const unordered_map<int64_t, int>& atomMatchingTrackerMap, unordered_map<int64_t, int>& conditionTrackerMap, vector<sp<ConditionTracker>>& allConditionTrackers, unordered_map<int, std::vector<int>>& trackerToConditionMap, @@ -310,7 +312,8 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config, switch (condition.contents_case()) { case Predicate::ContentsCase::kSimplePredicate: { allConditionTrackers.push_back(new SimpleConditionTracker( - key, condition.id(), index, condition.simple_predicate(), logTrackerMap)); + key, condition.id(), index, condition.simple_predicate(), + atomMatchingTrackerMap)); break; } case Predicate::ContentsCase::kCombination: { @@ -337,7 +340,7 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config, stackTracker, initialConditionCache)) { return false; } - for (const int trackerIndex : conditionTracker->getLogTrackerIndex()) { + for (const int trackerIndex : conditionTracker->getAtomMatchingTrackerIndex()) { auto& conditionList = trackerToConditionMap[trackerIndex]; conditionList.push_back(i); } @@ -365,9 +368,9 @@ bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAt bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs, const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager, - const unordered_map<int64_t, int>& logTrackerMap, + const unordered_map<int64_t, int>& atomMatchingTrackerMap, const unordered_map<int64_t, int>& conditionTrackerMap, - const vector<sp<LogMatchingTracker>>& allAtomMatchers, + const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const unordered_map<int64_t, int>& stateAtomIdMap, const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps, vector<sp<ConditionTracker>>& allConditionTrackers, @@ -380,7 +383,7 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap, vector<int>& metricsWithActivation) { sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers); - sp<EventMatcherWizard> matcherWizard = new EventMatcherWizard(allAtomMatchers); + sp<EventMatcherWizard> matcherWizard = new EventMatcherWizard(allAtomMatchingTrackers); const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() + config.event_metric_size() + config.gauge_metric_size() + config.value_metric_size(); @@ -411,9 +414,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t int metricIndex = allMetricProducers.size(); metricMap.insert({metric.id(), metricIndex}); int trackerIndex; - if (!handleMetricWithLogTrackers(metric.what(), metricIndex, - metric.has_dimensions_in_what(), allAtomMatchers, - logTrackerMap, trackerToMetricMap, trackerIndex)) { + if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex, + metric.has_dimensions_in_what(), + allAtomMatchingTrackers, atomMatchingTrackerMap, + trackerToMetricMap, trackerIndex)) { return false; } @@ -448,7 +452,7 @@ 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, + config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap, eventDeactivationMap); if (!success) return false; @@ -485,24 +489,27 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t int trackerIndices[3] = {-1, -1, -1}; if (!simplePredicate.has_start() || - !handleMetricWithLogTrackers(simplePredicate.start(), metricIndex, - metric.has_dimensions_in_what(), allAtomMatchers, - logTrackerMap, trackerToMetricMap, trackerIndices[0])) { + !handleMetricWithAtomMatchingTrackers(simplePredicate.start(), metricIndex, + metric.has_dimensions_in_what(), + allAtomMatchingTrackers, atomMatchingTrackerMap, + trackerToMetricMap, trackerIndices[0])) { ALOGE("Duration metrics must specify a valid the start event matcher"); return false; } if (simplePredicate.has_stop() && - !handleMetricWithLogTrackers(simplePredicate.stop(), metricIndex, - metric.has_dimensions_in_what(), allAtomMatchers, - logTrackerMap, trackerToMetricMap, trackerIndices[1])) { + !handleMetricWithAtomMatchingTrackers(simplePredicate.stop(), metricIndex, + metric.has_dimensions_in_what(), + allAtomMatchingTrackers, atomMatchingTrackerMap, + trackerToMetricMap, trackerIndices[1])) { return false; } if (simplePredicate.has_stop_all() && - !handleMetricWithLogTrackers(simplePredicate.stop_all(), metricIndex, - metric.has_dimensions_in_what(), allAtomMatchers, - logTrackerMap, trackerToMetricMap, trackerIndices[2])) { + !handleMetricWithAtomMatchingTrackers(simplePredicate.stop_all(), metricIndex, + metric.has_dimensions_in_what(), + allAtomMatchingTrackers, atomMatchingTrackerMap, + trackerToMetricMap, trackerIndices[2])) { return false; } @@ -554,7 +561,7 @@ 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, + config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap, eventDeactivationMap); if (!success) return false; @@ -578,8 +585,9 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t return false; } int trackerIndex; - if (!handleMetricWithLogTrackers(metric.what(), metricIndex, false, allAtomMatchers, - logTrackerMap, trackerToMetricMap, trackerIndex)) { + if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex, false, + allAtomMatchingTrackers, atomMatchingTrackerMap, + trackerToMetricMap, trackerIndex)) { return false; } @@ -601,7 +609,7 @@ 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, + config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap, eventDeactivationMap); if (!success) return false; @@ -634,13 +642,14 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t int metricIndex = allMetricProducers.size(); metricMap.insert({metric.id(), metricIndex}); int trackerIndex; - if (!handleMetricWithLogTrackers(metric.what(), metricIndex, - metric.has_dimensions_in_what(), allAtomMatchers, - logTrackerMap, trackerToMetricMap, trackerIndex)) { + if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex, + metric.has_dimensions_in_what(), + allAtomMatchingTrackers, atomMatchingTrackerMap, + trackerToMetricMap, trackerIndex)) { return false; } - sp<LogMatchingTracker> atomMatcher = allAtomMatchers.at(trackerIndex); + sp<AtomMatchingTracker> atomMatcher = allAtomMatchingTrackers.at(trackerIndex); // If it is pulled atom, it should be simple matcher with one tagId. if (atomMatcher->getAtomIds().size() != 1) { return false; @@ -689,7 +698,7 @@ 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, + config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap, eventDeactivationMap); if (!success) return false; @@ -725,13 +734,14 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t int metricIndex = allMetricProducers.size(); metricMap.insert({metric.id(), metricIndex}); int trackerIndex; - if (!handleMetricWithLogTrackers(metric.what(), metricIndex, - metric.has_dimensions_in_what(), allAtomMatchers, - logTrackerMap, trackerToMetricMap, trackerIndex)) { + if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex, + metric.has_dimensions_in_what(), + allAtomMatchingTrackers, atomMatchingTrackerMap, + trackerToMetricMap, trackerIndex)) { return false; } - sp<LogMatchingTracker> atomMatcher = allAtomMatchers.at(trackerIndex); + sp<AtomMatchingTracker> atomMatcher = allAtomMatchingTrackers.at(trackerIndex); // For GaugeMetric atom, it should be simple matcher with one tagId. if (atomMatcher->getAtomIds().size() != 1) { return false; @@ -750,12 +760,13 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t if (metric.sampling_type() != GaugeMetric::FIRST_N_SAMPLES) { return false; } - if (!handlePullMetricTriggerWithLogTrackers(metric.trigger_event(), metricIndex, - allAtomMatchers, logTrackerMap, - trackerToMetricMap, triggerTrackerIndex)) { + if (!handlePullMetricTriggerWithAtomMatchingTrackers( + metric.trigger_event(), metricIndex, allAtomMatchingTrackers, + atomMatchingTrackerMap, trackerToMetricMap, triggerTrackerIndex)) { return false; } - sp<LogMatchingTracker> triggerAtomMatcher = allAtomMatchers.at(triggerTrackerIndex); + sp<AtomMatchingTracker> triggerAtomMatcher = + allAtomMatchingTrackers.at(triggerTrackerIndex); triggerAtomId = *(triggerAtomMatcher->getAtomIds().begin()); } @@ -783,7 +794,7 @@ 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, + config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap, eventDeactivationMap); if (!success) return false; @@ -921,8 +932,8 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp 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<AtomMatchingTracker>>& allAtomMatchingTrackers, + unordered_map<int64_t, int>& atomMatchingTrackerMap, vector<sp<ConditionTracker>>& allConditionTrackers, vector<sp<MetricProducer>>& allMetricProducers, vector<sp<AnomalyTracker>>& allAnomalyTrackers, @@ -940,14 +951,15 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp unordered_map<int64_t, int> stateAtomIdMap; unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps; - if (!initLogTrackers(config, uidMap, logTrackerMap, allAtomMatchers, allTagIds)) { - ALOGE("initLogMatchingTrackers failed"); + if (!initAtomMatchingTrackers(config, uidMap, atomMatchingTrackerMap, allAtomMatchingTrackers, + allTagIds)) { + ALOGE("initAtomMatchingTrackers failed"); return false; } - VLOG("initLogMatchingTrackers succeed..."); + VLOG("initAtomMatchingTrackers succeed..."); - if (!initConditions(key, config, logTrackerMap, conditionTrackerMap, allConditionTrackers, - trackerToConditionMap, initialConditionCache)) { + if (!initConditions(key, config, atomMatchingTrackerMap, conditionTrackerMap, + allConditionTrackers, trackerToConditionMap, initialConditionCache)) { ALOGE("initConditionTrackers failed"); return false; } @@ -956,12 +968,12 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp ALOGE("initStates failed"); return false; } - if (!initMetrics(key, config, timeBaseNs, currentTimeNs, pullerManager, logTrackerMap, - conditionTrackerMap, allAtomMatchers, stateAtomIdMap, allStateGroupMaps, - allConditionTrackers, initialConditionCache, allMetricProducers, - conditionToMetricMap, trackerToMetricMap, metricProducerMap, noReportMetricIds, - activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, - metricsWithActivation)) { + if (!initMetrics(key, config, timeBaseNs, currentTimeNs, pullerManager, atomMatchingTrackerMap, + conditionTrackerMap, allAtomMatchingTrackers, stateAtomIdMap, + allStateGroupMaps, allConditionTrackers, initialConditionCache, + allMetricProducers, conditionToMetricMap, trackerToMetricMap, + metricProducerMap, noReportMetricIds, activationAtomTrackerToMetricMap, + deactivationAtomTrackerToMetricMap, metricsWithActivation)) { ALOGE("initMetricProducers failed"); return false; } diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h index ed9951fd5ee6..4cfd1b0465ea 100644 --- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h +++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h @@ -23,7 +23,7 @@ #include "anomaly/AlarmTracker.h" #include "condition/ConditionTracker.h" #include "external/StatsPullerManager.h" -#include "matchers/LogMatchingTracker.h" +#include "matchers/AtomMatchingTracker.h" #include "metrics/MetricProducer.h" namespace android { @@ -33,14 +33,14 @@ 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. +// Create a AtomMatchingTracker. // 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); +// new AtomMatchingTracker, or null if the tracker is unable to be created +sp<AtomMatchingTracker> createAtomMatchingTracker(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. @@ -48,24 +48,24 @@ sp<LogMatchingTracker> createLogTracker(const AtomMatcher& logMatcher, const int // steps, created to make unit tests easier. And most of the parameters in these // functions are temporary objects in the initialization phase. -// Initialize the LogMatchingTrackers. +// Initialize the AtomMatchingTrackers. // input: // [key]: the config key that this config belongs to // [config]: the input StatsdConfig // output: -// [logTrackerMap]: this map should contain matcher name to index mapping -// [allAtomMatchers]: should store the sp to all the LogMatchingTracker +// [atomMatchingTrackerMap]: this map should contain matcher name to index mapping +// [allAtomMatchingTrackers]: should store the sp to all the AtomMatchingTracker // [allTagIds]: contains the set of all interesting tag ids to this config. -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); +bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap, + std::unordered_map<int64_t, int>& atomMatchingTrackerMap, + std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, + std::set<int>& allTagIds); // Initialize ConditionTrackers // input: // [key]: the config key that this config belongs to // [config]: the input config -// [logTrackerMap]: LogMatchingTracker name to index mapping from previous step. +// [atomMatchingTrackerMap]: AtomMatchingTracker name to index mapping from previous step. // output: // [conditionTrackerMap]: this map should contain condition name to index mapping // [allConditionTrackers]: stores the sp to all the ConditionTrackers @@ -73,7 +73,7 @@ bool initLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap, // log tracker to condition trackers that use the log tracker // [initialConditionCache]: stores the initial conditions for each ConditionTracker bool initConditions(const ConfigKey& key, const StatsdConfig& config, - const std::unordered_map<int64_t, int>& logTrackerMap, + const std::unordered_map<int64_t, int>& atomMatchingTrackerMap, std::unordered_map<int64_t, int>& conditionTrackerMap, std::vector<sp<ConditionTracker>>& allConditionTrackers, std::unordered_map<int, std::vector<int>>& trackerToConditionMap, @@ -96,7 +96,7 @@ bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAt // [key]: the config key that this config belongs to // [config]: the input config // [timeBaseSec]: start time base for all metrics -// [logTrackerMap]: LogMatchingTracker name to index mapping from previous step. +// [atomMatchingTrackerMap]: AtomMatchingTracker name to index mapping from previous step. // [conditionTrackerMap]: condition name to index mapping // [stateAtomIdMap]: contains the mapping from state ids to atom ids // [allStateGroupMaps]: contains the mapping from atom ids and state values to @@ -109,10 +109,10 @@ bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAt bool initMetrics( const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs, const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager, - const std::unordered_map<int64_t, int>& logTrackerMap, + const std::unordered_map<int64_t, int>& atomMatchingTrackerMap, const std::unordered_map<int64_t, int>& conditionTrackerMap, const std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks, - const vector<sp<LogMatchingTracker>>& allAtomMatchers, + const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const unordered_map<int64_t, int>& stateAtomIdMap, const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps, vector<sp<ConditionTracker>>& allConditionTrackers, @@ -132,8 +132,8 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp 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<AtomMatchingTracker>>& allAtomMatchingTrackers, + std::unordered_map<int64_t, int>& atomMatchingTrackerMap, std::vector<sp<ConditionTracker>>& allConditionTrackers, std::vector<sp<MetricProducer>>& allMetricProducers, vector<sp<AnomalyTracker>>& allAnomalyTrackers, diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h index eb65dc6979c5..10e065e4113f 100644 --- a/cmds/statsd/src/stats_log_util.h +++ b/cmds/statsd/src/stats_log_util.h @@ -97,7 +97,7 @@ bool parseProtoOutputStream(ProtoOutputStream& protoOutput, T* message) { return message->ParseFromArray(pbBytes.c_str(), pbBytes.size()); } -// Checks the truncate timestamp annotation as well as the blacklisted range of 300,000 - 304,999. +// Checks the truncate timestamp annotation as well as the restricted range of 300,000 - 304,999. // Returns the truncated timestamp to the nearest 5 minutes if needed. int64_t truncateTimestampIfNecessary(const LogEvent& event); diff --git a/cmds/statsd/tests/MetricsManager_test.cpp b/cmds/statsd/tests/MetricsManager_test.cpp index 8dd608347064..2dd774e7dfc9 100644 --- a/cmds/statsd/tests/MetricsManager_test.cpp +++ b/cmds/statsd/tests/MetricsManager_test.cpp @@ -23,7 +23,7 @@ #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" #include "metrics/metrics_test_helper.h" #include "src/condition/ConditionTracker.h" -#include "src/matchers/LogMatchingTracker.h" +#include "src/matchers/AtomMatchingTracker.h" #include "src/metrics/CountMetricProducer.h" #include "src/metrics/GaugeMetricProducer.h" #include "src/metrics/MetricProducer.h" diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp index 1e6680c47567..1409b621fdf6 100644 --- a/cmds/statsd/tests/StatsLogProcessor_test.cpp +++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp @@ -68,7 +68,7 @@ TEST(StatsLogProcessorTest, TestRateLimitByteSize) { sp<StatsPullerManager> pullerManager = new StatsPullerManager(); sp<AlarmMonitor> anomalyAlarmMonitor; sp<AlarmMonitor> periodicAlarmMonitor; - // Construct the processor with a dummy sendBroadcast function that does nothing. + // Construct the processor with a no-op sendBroadcast function that does nothing. StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, 0, [](const ConfigKey& key) { return true; }, [](const int&, const vector<int64_t>&) {return true;}); @@ -896,8 +896,8 @@ TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) { EXPECT_TRUE(metricProducer2->isActive()); int i = 0; - for (; i < metricsManager1->mAllAtomMatchers.size(); i++) { - if (metricsManager1->mAllAtomMatchers[i]->getId() == + for (; i < metricsManager1->mAllAtomMatchingTrackers.size(); i++) { + if (metricsManager1->mAllAtomMatchingTrackers[i]->getId() == metric1ActivationTrigger1->atom_matcher_id()) { break; } @@ -908,8 +908,8 @@ TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) { EXPECT_EQ(kNotActive, activation1->state); i = 0; - for (; i < metricsManager1->mAllAtomMatchers.size(); i++) { - if (metricsManager1->mAllAtomMatchers[i]->getId() == + for (; i < metricsManager1->mAllAtomMatchingTrackers.size(); i++) { + if (metricsManager1->mAllAtomMatchingTrackers[i]->getId() == metric1ActivationTrigger2->atom_matcher_id()) { break; } @@ -981,8 +981,8 @@ TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) { EXPECT_TRUE(metricProducer1002->isActive()); i = 0; - for (; i < metricsManager1001->mAllAtomMatchers.size(); i++) { - if (metricsManager1001->mAllAtomMatchers[i]->getId() == + for (; i < metricsManager1001->mAllAtomMatchingTrackers.size(); i++) { + if (metricsManager1001->mAllAtomMatchingTrackers[i]->getId() == metric1ActivationTrigger1->atom_matcher_id()) { break; } @@ -993,8 +993,8 @@ TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) { EXPECT_EQ(kNotActive, activation1001_1->state); i = 0; - for (; i < metricsManager1001->mAllAtomMatchers.size(); i++) { - if (metricsManager1001->mAllAtomMatchers[i]->getId() == + for (; i < metricsManager1001->mAllAtomMatchingTrackers.size(); i++) { + if (metricsManager1001->mAllAtomMatchingTrackers[i]->getId() == metric1ActivationTrigger2->atom_matcher_id()) { break; } @@ -1082,8 +1082,8 @@ TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) { EXPECT_TRUE(metricProducerTimeBase3_2->isActive()); i = 0; - for (; i < metricsManagerTimeBase3->mAllAtomMatchers.size(); i++) { - if (metricsManagerTimeBase3->mAllAtomMatchers[i]->getId() == + for (; i < metricsManagerTimeBase3->mAllAtomMatchingTrackers.size(); i++) { + if (metricsManagerTimeBase3->mAllAtomMatchingTrackers[i]->getId() == metric1ActivationTrigger1->atom_matcher_id()) { break; } @@ -1094,8 +1094,8 @@ TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) { EXPECT_EQ(kNotActive, activationTimeBase3_1->state); i = 0; - for (; i < metricsManagerTimeBase3->mAllAtomMatchers.size(); i++) { - if (metricsManagerTimeBase3->mAllAtomMatchers[i]->getId() == + for (; i < metricsManagerTimeBase3->mAllAtomMatchingTrackers.size(); i++) { + if (metricsManagerTimeBase3->mAllAtomMatchingTrackers[i]->getId() == metric1ActivationTrigger2->atom_matcher_id()) { break; } @@ -1184,8 +1184,8 @@ TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) { EXPECT_TRUE(metricProducerTimeBase4_2->isActive()); i = 0; - for (; i < metricsManagerTimeBase4->mAllAtomMatchers.size(); i++) { - if (metricsManagerTimeBase4->mAllAtomMatchers[i]->getId() == + for (; i < metricsManagerTimeBase4->mAllAtomMatchingTrackers.size(); i++) { + if (metricsManagerTimeBase4->mAllAtomMatchingTrackers[i]->getId() == metric1ActivationTrigger1->atom_matcher_id()) { break; } @@ -1196,8 +1196,8 @@ TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) { EXPECT_EQ(kNotActive, activationTimeBase4_1->state); i = 0; - for (; i < metricsManagerTimeBase4->mAllAtomMatchers.size(); i++) { - if (metricsManagerTimeBase4->mAllAtomMatchers[i]->getId() == + for (; i < metricsManagerTimeBase4->mAllAtomMatchingTrackers.size(); i++) { + if (metricsManagerTimeBase4->mAllAtomMatchingTrackers[i]->getId() == metric1ActivationTrigger2->atom_matcher_id()) { break; } @@ -1585,8 +1585,8 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) { EXPECT_TRUE(metricProducer3->isActive()); // Check event activations. - ASSERT_EQ(metricsManager1->mAllAtomMatchers.size(), 4); - EXPECT_EQ(metricsManager1->mAllAtomMatchers[0]->getId(), + ASSERT_EQ(metricsManager1->mAllAtomMatchingTrackers.size(), 4); + EXPECT_EQ(metricsManager1->mAllAtomMatchingTrackers[0]->getId(), metric1ActivationTrigger1->atom_matcher_id()); const auto& activation1 = metricProducer1->mEventActivationMap.at(0); EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns); @@ -1594,7 +1594,7 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) { EXPECT_EQ(kNotActive, activation1->state); EXPECT_EQ(ACTIVATE_ON_BOOT, activation1->activationType); - EXPECT_EQ(metricsManager1->mAllAtomMatchers[1]->getId(), + EXPECT_EQ(metricsManager1->mAllAtomMatchingTrackers[1]->getId(), metric1ActivationTrigger2->atom_matcher_id()); const auto& activation2 = metricProducer1->mEventActivationMap.at(1); EXPECT_EQ(200 * NS_PER_SEC, activation2->ttl_ns); @@ -1602,7 +1602,7 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) { EXPECT_EQ(kNotActive, activation2->state); EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation2->activationType); - EXPECT_EQ(metricsManager1->mAllAtomMatchers[2]->getId(), + EXPECT_EQ(metricsManager1->mAllAtomMatchingTrackers[2]->getId(), metric2ActivationTrigger1->atom_matcher_id()); const auto& activation3 = metricProducer2->mEventActivationMap.at(2); EXPECT_EQ(100 * NS_PER_SEC, activation3->ttl_ns); @@ -1610,7 +1610,7 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) { EXPECT_EQ(kNotActive, activation3->state); EXPECT_EQ(ACTIVATE_ON_BOOT, activation3->activationType); - EXPECT_EQ(metricsManager1->mAllAtomMatchers[3]->getId(), + EXPECT_EQ(metricsManager1->mAllAtomMatchingTrackers[3]->getId(), metric2ActivationTrigger2->atom_matcher_id()); const auto& activation4 = metricProducer2->mEventActivationMap.at(3); EXPECT_EQ(200 * NS_PER_SEC, activation4->ttl_ns); @@ -1685,8 +1685,8 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) { // Activation 1 is kActiveOnBoot. // Activation 2 and 3 are not active. // Activation 4 is active. - ASSERT_EQ(metricsManager2->mAllAtomMatchers.size(), 4); - EXPECT_EQ(metricsManager2->mAllAtomMatchers[0]->getId(), + ASSERT_EQ(metricsManager2->mAllAtomMatchingTrackers.size(), 4); + EXPECT_EQ(metricsManager2->mAllAtomMatchingTrackers[0]->getId(), metric1ActivationTrigger1->atom_matcher_id()); const auto& activation1001 = metricProducer1001->mEventActivationMap.at(0); EXPECT_EQ(100 * NS_PER_SEC, activation1001->ttl_ns); @@ -1694,7 +1694,7 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) { EXPECT_EQ(kActiveOnBoot, activation1001->state); EXPECT_EQ(ACTIVATE_ON_BOOT, activation1001->activationType); - EXPECT_EQ(metricsManager2->mAllAtomMatchers[1]->getId(), + EXPECT_EQ(metricsManager2->mAllAtomMatchingTrackers[1]->getId(), metric1ActivationTrigger2->atom_matcher_id()); const auto& activation1002 = metricProducer1001->mEventActivationMap.at(1); EXPECT_EQ(200 * NS_PER_SEC, activation1002->ttl_ns); @@ -1702,7 +1702,7 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) { EXPECT_EQ(kNotActive, activation1002->state); EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1002->activationType); - EXPECT_EQ(metricsManager2->mAllAtomMatchers[2]->getId(), + EXPECT_EQ(metricsManager2->mAllAtomMatchingTrackers[2]->getId(), metric2ActivationTrigger1->atom_matcher_id()); const auto& activation1003 = metricProducer1002->mEventActivationMap.at(2); EXPECT_EQ(100 * NS_PER_SEC, activation1003->ttl_ns); @@ -1710,7 +1710,7 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) { EXPECT_EQ(kNotActive, activation1003->state); EXPECT_EQ(ACTIVATE_ON_BOOT, activation1003->activationType); - EXPECT_EQ(metricsManager2->mAllAtomMatchers[3]->getId(), + EXPECT_EQ(metricsManager2->mAllAtomMatchingTrackers[3]->getId(), metric2ActivationTrigger2->atom_matcher_id()); const auto& activation1004 = metricProducer1002->mEventActivationMap.at(3); EXPECT_EQ(200 * NS_PER_SEC, activation1004->ttl_ns); diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp index 293e8ed1c44c..33bdc64333e0 100644 --- a/cmds/statsd/tests/UidMap_test.cpp +++ b/cmds/statsd/tests/UidMap_test.cpp @@ -44,7 +44,7 @@ TEST(UidMapTest, TestIsolatedUID) { sp<StatsPullerManager> pullerManager = new StatsPullerManager(); sp<AlarmMonitor> anomalyAlarmMonitor; sp<AlarmMonitor> subscriberAlarmMonitor; - // Construct the processor with a dummy sendBroadcast function that does nothing. + // Construct the processor with a no-op sendBroadcast function that does nothing. StatsLogProcessor p( m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0, [](const ConfigKey& key) { return true; }, diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp index d96ff8a1925b..ba919f1e0ad8 100644 --- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp @@ -23,7 +23,7 @@ #include "logd/LogEvent.h" #include "metrics_test_helper.h" -#include "src/matchers/SimpleLogMatchingTracker.h" +#include "src/matchers/SimpleAtomMatchingTracker.h" #include "src/metrics/MetricProducer.h" #include "src/stats_log_util.h" #include "stats_event.h" diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp index 5524ebc86b36..1000aea14868 100644 --- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp @@ -22,7 +22,7 @@ #include <vector> #include "metrics_test_helper.h" -#include "src/matchers/SimpleLogMatchingTracker.h" +#include "src/matchers/SimpleAtomMatchingTracker.h" #include "src/metrics/MetricProducer.h" #include "src/stats_log_util.h" #include "tests/statsd_test_util.h" 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 index 6b50fe5387d7..f6d30618ee15 100644 --- a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp +++ b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp @@ -49,8 +49,8 @@ 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<AtomMatchingTracker>> oldAtomMatchingTrackers; +unordered_map<int64_t, int> oldAtomMatchingTrackerMap; vector<sp<ConditionTracker>> oldConditionTrackers; vector<sp<MetricProducer>> oldMetricProducers; std::vector<sp<AnomalyTracker>> oldAnomalyTrackers; @@ -71,8 +71,8 @@ public: void SetUp() override { allTagIds.clear(); - oldAtomMatchers.clear(); - oldLogTrackerMap.clear(); + oldAtomMatchingTrackers.clear(); + oldAtomMatchingTrackerMap.clear(); oldConditionTrackers.clear(); oldMetricProducers.clear(); oldAnomalyTrackers.clear(); @@ -89,13 +89,13 @@ public: }; 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); + return initStatsdConfig( + key, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, + timeBaseNs, timeBaseNs, allTagIds, oldAtomMatchingTrackers, oldAtomMatchingTrackerMap, + oldConditionTrackers, oldMetricProducers, oldAnomalyTrackers, oldAlarmTrackers, + conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, + activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, + metricsWithActivation, noReportMetricIds); } } // anonymous namespace @@ -111,10 +111,11 @@ TEST_F(ConfigUpdateTest, TestSimpleMatcherPreserve) { 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)); + unordered_map<int64_t, int> newAtomMatchingTrackerMap; + newAtomMatchingTrackerMap[matcherId] = 0; + EXPECT_TRUE(determineMatcherUpdateStatus(config, 0, oldAtomMatchingTrackerMap, + oldAtomMatchingTrackers, newAtomMatchingTrackerMap, + matchersToUpdate, cycleTracker)); EXPECT_EQ(matchersToUpdate[0], UPDATE_PRESERVE); } @@ -134,10 +135,11 @@ TEST_F(ConfigUpdateTest, TestSimpleMatcherReplace) { 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)); + unordered_map<int64_t, int> newAtomMatchingTrackerMap; + newAtomMatchingTrackerMap[matcherId] = 0; + EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 0, oldAtomMatchingTrackerMap, + oldAtomMatchingTrackers, newAtomMatchingTrackerMap, + matchersToUpdate, cycleTracker)); EXPECT_EQ(matchersToUpdate[0], UPDATE_REPLACE); } @@ -163,20 +165,21 @@ TEST_F(ConfigUpdateTest, TestCombinationMatcherPreserve) { EXPECT_TRUE(initConfig(config)); StatsdConfig newConfig; - unordered_map<int64_t, int> newLogTrackerMap; + unordered_map<int64_t, int> newAtomMatchingTrackerMap; // Same matchers, different order, all should be preserved. *newConfig.add_atom_matcher() = matcher2; - newLogTrackerMap[matcher2Id] = 0; + newAtomMatchingTrackerMap[matcher2Id] = 0; *newConfig.add_atom_matcher() = matcher3; - newLogTrackerMap[matcher3Id] = 1; + newAtomMatchingTrackerMap[matcher3Id] = 1; *newConfig.add_atom_matcher() = matcher1; - newLogTrackerMap[matcher1Id] = 2; + newAtomMatchingTrackerMap[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_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap, + oldAtomMatchingTrackers, newAtomMatchingTrackerMap, + matchersToUpdate, cycleTracker)); EXPECT_EQ(matchersToUpdate[0], UPDATE_PRESERVE); EXPECT_EQ(matchersToUpdate[1], UPDATE_PRESERVE); EXPECT_EQ(matchersToUpdate[2], UPDATE_PRESERVE); @@ -207,19 +210,20 @@ TEST_F(ConfigUpdateTest, TestCombinationMatcherReplace) { matcher3.mutable_combination()->set_operation(LogicalOperation::AND); StatsdConfig newConfig; - unordered_map<int64_t, int> newLogTrackerMap; + unordered_map<int64_t, int> newAtomMatchingTrackerMap; *newConfig.add_atom_matcher() = matcher2; - newLogTrackerMap[matcher2Id] = 0; + newAtomMatchingTrackerMap[matcher2Id] = 0; *newConfig.add_atom_matcher() = matcher3; - newLogTrackerMap[matcher3Id] = 1; + newAtomMatchingTrackerMap[matcher3Id] = 1; *newConfig.add_atom_matcher() = matcher1; - newLogTrackerMap[matcher1Id] = 2; + newAtomMatchingTrackerMap[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_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap, + oldAtomMatchingTrackers, newAtomMatchingTrackerMap, + matchersToUpdate, cycleTracker)); EXPECT_EQ(matchersToUpdate[0], UPDATE_UNKNOWN); EXPECT_EQ(matchersToUpdate[1], UPDATE_REPLACE); EXPECT_EQ(matchersToUpdate[2], UPDATE_UNKNOWN); @@ -250,19 +254,20 @@ TEST_F(ConfigUpdateTest, TestCombinationMatcherDepsChange) { matcher2.mutable_simple_atom_matcher()->set_atom_id(12); StatsdConfig newConfig; - unordered_map<int64_t, int> newLogTrackerMap; + unordered_map<int64_t, int> newAtomMatchingTrackerMap; *newConfig.add_atom_matcher() = matcher2; - newLogTrackerMap[matcher2Id] = 0; + newAtomMatchingTrackerMap[matcher2Id] = 0; *newConfig.add_atom_matcher() = matcher3; - newLogTrackerMap[matcher3Id] = 1; + newAtomMatchingTrackerMap[matcher3Id] = 1; *newConfig.add_atom_matcher() = matcher1; - newLogTrackerMap[matcher1Id] = 2; + newAtomMatchingTrackerMap[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)); + EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap, + oldAtomMatchingTrackers, newAtomMatchingTrackerMap, + 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); @@ -330,47 +335,48 @@ TEST_F(ConfigUpdateTest, TestUpdateMatchers) { *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)); + unordered_map<int64_t, int> newAtomMatchingTrackerMap; + vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers; + EXPECT_TRUE(updateAtomTrackers(newConfig, uidMap, oldAtomMatchingTrackerMap, + oldAtomMatchingTrackers, newTagIds, newAtomMatchingTrackerMap, + newAtomMatchingTrackers)); 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(newAtomMatchingTrackerMap.size(), 6); + EXPECT_EQ(newAtomMatchingTrackerMap.at(combination3Id), 0); + EXPECT_EQ(newAtomMatchingTrackerMap.at(simple2Id), 1); + EXPECT_EQ(newAtomMatchingTrackerMap.at(combination2Id), 2); + EXPECT_EQ(newAtomMatchingTrackerMap.at(simple1Id), 3); + EXPECT_EQ(newAtomMatchingTrackerMap.at(simple4Id), 4); + EXPECT_EQ(newAtomMatchingTrackerMap.at(combination1Id), 5); - ASSERT_EQ(newAtomMatchers.size(), 6); + ASSERT_EQ(newAtomMatchingTrackers.size(), 6); // Make sure all atom matchers are initialized: - for (const sp<LogMatchingTracker>& tracker : newAtomMatchers) { + for (const sp<AtomMatchingTracker>& tracker : newAtomMatchingTrackers) { 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)]); + EXPECT_EQ(oldAtomMatchingTrackers[oldAtomMatchingTrackerMap.at(simple1Id)], + newAtomMatchingTrackers[newAtomMatchingTrackerMap.at(simple1Id)]); + EXPECT_EQ(oldAtomMatchingTrackers[oldAtomMatchingTrackerMap.at(combination1Id)], + newAtomMatchingTrackers[newAtomMatchingTrackerMap.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)]); + EXPECT_NE(oldAtomMatchingTrackers[oldAtomMatchingTrackerMap.at(simple2Id)], + newAtomMatchingTrackers[newAtomMatchingTrackerMap.at(simple2Id)]); + EXPECT_NE(oldAtomMatchingTrackers[oldAtomMatchingTrackerMap.at(combination2Id)], + newAtomMatchingTrackers[newAtomMatchingTrackerMap.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); + EXPECT_EQ(newAtomMatchingTrackers[0]->getId(), combination3Id); + EXPECT_EQ(newAtomMatchingTrackers[1]->getId(), simple2Id); + EXPECT_EQ(newAtomMatchingTrackers[2]->getId(), combination2Id); + EXPECT_EQ(newAtomMatchingTrackers[3]->getId(), simple1Id); + EXPECT_EQ(newAtomMatchingTrackers[4]->getId(), simple4Id); + EXPECT_EQ(newAtomMatchingTrackers[5]->getId(), combination1Id); } } // namespace statsd 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 index 4e97eaf6f149..d6db4c12ae4d 100644 --- a/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp +++ b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp @@ -24,7 +24,7 @@ #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" #include "src/condition/ConditionTracker.h" -#include "src/matchers/LogMatchingTracker.h" +#include "src/matchers/AtomMatchingTracker.h" #include "src/metrics/CountMetricProducer.h" #include "src/metrics/GaugeMetricProducer.h" #include "src/metrics/MetricProducer.h" @@ -383,7 +383,7 @@ TEST(MetricsManagerTest, TestInitialConditions) { sp<AlarmMonitor> periodicAlarmMonitor; StatsdConfig config = buildConfigWithDifferentPredicates(); set<int> allTagIds; - vector<sp<LogMatchingTracker>> allAtomMatchers; + vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers; unordered_map<int64_t, int> logTrackerMap; vector<sp<ConditionTracker>> allConditionTrackers; vector<sp<MetricProducer>> allMetricProducers; @@ -400,7 +400,7 @@ TEST(MetricsManagerTest, TestInitialConditions) { EXPECT_TRUE(initStatsdConfig( kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, - timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap, allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, @@ -432,7 +432,7 @@ TEST(MetricsManagerTest, TestGoodConfig) { sp<AlarmMonitor> periodicAlarmMonitor; StatsdConfig config = buildGoodConfig(); set<int> allTagIds; - vector<sp<LogMatchingTracker>> allAtomMatchers; + vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers; unordered_map<int64_t, int> logTrackerMap; vector<sp<ConditionTracker>> allConditionTrackers; vector<sp<MetricProducer>> allMetricProducers; @@ -449,7 +449,7 @@ TEST(MetricsManagerTest, TestGoodConfig) { EXPECT_TRUE(initStatsdConfig( kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, - timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap, allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, @@ -469,7 +469,7 @@ TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) { sp<AlarmMonitor> periodicAlarmMonitor; StatsdConfig config = buildDimensionMetricsWithMultiTags(); set<int> allTagIds; - vector<sp<LogMatchingTracker>> allAtomMatchers; + vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers; unordered_map<int64_t, int> logTrackerMap; vector<sp<ConditionTracker>> allConditionTrackers; vector<sp<MetricProducer>> allMetricProducers; @@ -486,7 +486,7 @@ TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) { EXPECT_FALSE(initStatsdConfig( kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, - timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap, allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, @@ -500,7 +500,7 @@ TEST(MetricsManagerTest, TestCircleLogMatcherDependency) { sp<AlarmMonitor> periodicAlarmMonitor; StatsdConfig config = buildCircleMatchers(); set<int> allTagIds; - vector<sp<LogMatchingTracker>> allAtomMatchers; + vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers; unordered_map<int64_t, int> logTrackerMap; vector<sp<ConditionTracker>> allConditionTrackers; vector<sp<MetricProducer>> allMetricProducers; @@ -517,7 +517,7 @@ TEST(MetricsManagerTest, TestCircleLogMatcherDependency) { EXPECT_FALSE(initStatsdConfig( kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, - timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap, allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, @@ -531,7 +531,7 @@ TEST(MetricsManagerTest, TestMissingMatchers) { sp<AlarmMonitor> periodicAlarmMonitor; StatsdConfig config = buildMissingMatchers(); set<int> allTagIds; - vector<sp<LogMatchingTracker>> allAtomMatchers; + vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers; unordered_map<int64_t, int> logTrackerMap; vector<sp<ConditionTracker>> allConditionTrackers; vector<sp<MetricProducer>> allMetricProducers; @@ -547,7 +547,7 @@ TEST(MetricsManagerTest, TestMissingMatchers) { std::set<int64_t> noReportMetricIds; EXPECT_FALSE(initStatsdConfig( kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, - timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap, allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, @@ -561,7 +561,7 @@ TEST(MetricsManagerTest, TestMissingPredicate) { sp<AlarmMonitor> periodicAlarmMonitor; StatsdConfig config = buildMissingPredicate(); set<int> allTagIds; - vector<sp<LogMatchingTracker>> allAtomMatchers; + vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers; unordered_map<int64_t, int> logTrackerMap; vector<sp<ConditionTracker>> allConditionTrackers; vector<sp<MetricProducer>> allMetricProducers; @@ -577,7 +577,7 @@ TEST(MetricsManagerTest, TestMissingPredicate) { std::set<int64_t> noReportMetricIds; EXPECT_FALSE(initStatsdConfig( kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, - timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap, allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, @@ -591,7 +591,7 @@ TEST(MetricsManagerTest, TestCirclePredicateDependency) { sp<AlarmMonitor> periodicAlarmMonitor; StatsdConfig config = buildCirclePredicates(); set<int> allTagIds; - vector<sp<LogMatchingTracker>> allAtomMatchers; + vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers; unordered_map<int64_t, int> logTrackerMap; vector<sp<ConditionTracker>> allConditionTrackers; vector<sp<MetricProducer>> allMetricProducers; @@ -608,7 +608,7 @@ TEST(MetricsManagerTest, TestCirclePredicateDependency) { EXPECT_FALSE(initStatsdConfig( kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, - timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap, allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, @@ -622,7 +622,7 @@ TEST(MetricsManagerTest, testAlertWithUnknownMetric) { sp<AlarmMonitor> periodicAlarmMonitor; StatsdConfig config = buildAlertWithUnknownMetric(); set<int> allTagIds; - vector<sp<LogMatchingTracker>> allAtomMatchers; + vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers; unordered_map<int64_t, int> logTrackerMap; vector<sp<ConditionTracker>> allConditionTrackers; vector<sp<MetricProducer>> allMetricProducers; @@ -639,21 +639,21 @@ TEST(MetricsManagerTest, testAlertWithUnknownMetric) { EXPECT_FALSE(initStatsdConfig( kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, - timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap, + timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap, allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation, noReportMetricIds)); } -TEST(MetricsManagerTest, TestCreateLogTrackerInvalidMatcher) { +TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerInvalidMatcher) { sp<UidMap> uidMap = new UidMap(); AtomMatcher matcher; matcher.set_id(21); - EXPECT_EQ(createLogTracker(matcher, 0, uidMap), nullptr); + EXPECT_EQ(createAtomMatchingTracker(matcher, 0, uidMap), nullptr); } -TEST(MetricsManagerTest, TestCreateLogTrackerSimple) { +TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerSimple) { int index = 1; int64_t id = 123; sp<UidMap> uidMap = new UidMap(); @@ -666,7 +666,7 @@ TEST(MetricsManagerTest, TestCreateLogTrackerSimple) { simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( android::view::DisplayStateEnum::DISPLAY_STATE_ON); - sp<LogMatchingTracker> tracker = createLogTracker(matcher, index, uidMap); + sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(matcher, index, uidMap); EXPECT_NE(tracker, nullptr); EXPECT_TRUE(tracker->mInitialized); @@ -677,7 +677,7 @@ TEST(MetricsManagerTest, TestCreateLogTrackerSimple) { EXPECT_EQ(atomIds.count(util::SCREEN_STATE_CHANGED), 1); } -TEST(MetricsManagerTest, TestCreateLogTrackerCombination) { +TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerCombination) { int index = 1; int64_t id = 123; sp<UidMap> uidMap = new UidMap(); @@ -688,7 +688,7 @@ TEST(MetricsManagerTest, TestCreateLogTrackerCombination) { combination->add_matcher(123); combination->add_matcher(223); - sp<LogMatchingTracker> tracker = createLogTracker(matcher, index, uidMap); + sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(matcher, index, uidMap); EXPECT_NE(tracker, nullptr); // Combination matchers need to be initialized first. diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp index 0be983f2a9b0..1761d5d9e1fa 100644 --- a/cmds/statsd/tests/statsd_test_util.cpp +++ b/cmds/statsd/tests/statsd_test_util.cpp @@ -16,7 +16,7 @@ #include <aidl/android/util/StatsEventParcel.h> -#include "matchers/SimpleLogMatchingTracker.h" +#include "matchers/SimpleAtomMatchingTracker.h" #include "stats_event.h" using aidl::android::util::StatsEventParcel; @@ -1008,8 +1008,8 @@ sp<EventMatcherWizard> createEventMatcherWizard( } uint64_t matcherHash = 0x12345678; int64_t matcherId = 678; - return new EventMatcherWizard({new SimpleLogMatchingTracker(matcherId, matcherIndex, - matcherHash, atomMatcher, uidMap)}); + return new EventMatcherWizard({new SimpleAtomMatchingTracker( + matcherId, matcherIndex, matcherHash, atomMatcher, uidMap)}); } void ValidateWakelockAttributionUidAndTagDimension(const DimensionsValue& value, const int atomId, diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java index 15237beee805..08cd0b34ee0a 100644 --- a/core/java/android/app/ApplicationLoaders.java +++ b/core/java/android/app/ApplicationLoaders.java @@ -243,8 +243,8 @@ public class ApplicationLoaders { // cached must be built and loaded in the same environment if (!sharedLibrariesEquals(sharedLibraries, cached.sharedLibraries)) { - Log.w(TAG, "Unexpected environment for cached library: (" + sharedLibraries + "|" - + cached.sharedLibraries + ")"); + Log.w(TAG, "Unexpected environment loading cached library " + zip + " (real|cached): (" + + sharedLibraries + "|" + cached.sharedLibraries + ")"); return null; } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 6f3e89229e4c..6737972dc34e 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -5187,19 +5187,11 @@ public class Notification implements Parcelable bindHeaderChronometerAndTime(contentView, p); bindProfileBadge(contentView, p); bindAlertedIcon(contentView, p); - bindActivePermissions(contentView, p); bindFeedbackIcon(contentView, p); bindExpandButton(contentView, p); mN.mUsesStandardHeader = true; } - private void bindActivePermissions(RemoteViews contentView, StandardTemplateParams p) { - int color = getNeutralColor(p); - contentView.setDrawableTint(R.id.camera, false, color, PorterDuff.Mode.SRC_ATOP); - contentView.setDrawableTint(R.id.mic, false, color, PorterDuff.Mode.SRC_ATOP); - contentView.setDrawableTint(R.id.overlay, false, color, PorterDuff.Mode.SRC_ATOP); - } - private void bindFeedbackIcon(RemoteViews contentView, StandardTemplateParams p) { int color = getNeutralColor(p); contentView.setDrawableTint(R.id.feedback, false, color, PorterDuff.Mode.SRC_ATOP); diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 8ee995d6e6be..0627bc855934 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -282,6 +282,16 @@ public class NotificationManager { = "android.app.action.INTERRUPTION_FILTER_CHANGED"; /** + * Intent that is broadcast when the state of + * {@link #hasEnabledNotificationListener(String, UserHandle)} changes. + * @hide + */ + @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final String ACTION_NOTIFICATION_LISTENER_ENABLED_CHANGED = + "android.app.action.NOTIFICATION_LISTENER_ENABLED_CHANGED"; + + /** * Intent that is broadcast when the state of getCurrentInterruptionFilter() changes. * @hide */ diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java index 54f3f1026050..6c6c04e4e975 100644 --- a/core/java/android/app/PropertyInvalidatedCache.java +++ b/core/java/android/app/PropertyInvalidatedCache.java @@ -413,7 +413,7 @@ public abstract class PropertyInvalidatedCache<Query, Result> { public final void disableLocal() { synchronized (mLock) { mDisabled = true; - mCache.clear(); + clear(); } } @@ -463,7 +463,7 @@ public abstract class PropertyInvalidatedCache<Query, Result> { cacheName(), mCache.size(), mLastSeenNonce, currentNonce)); } - mCache.clear(); + clear(); mLastSeenNonce = currentNonce; cachedResult = null; } @@ -728,9 +728,13 @@ public abstract class PropertyInvalidatedCache<Query, Result> { * It's better to use explicit cork and uncork pairs that tighly surround big batches of * invalidations, but it's not always practical to tell where these invalidation batches * might occur. AutoCorker's time-based corking is a decent alternative. + * + * The auto-cork delay is configurable but it should not be too long. The purpose of + * the delay is to minimize the number of times a server writes to the system property + * when invalidating the cache. One write every 50ms does not hurt system performance. */ public static final class AutoCorker { - public static final int DEFAULT_AUTO_CORK_DELAY_MS = 2000; + public static final int DEFAULT_AUTO_CORK_DELAY_MS = 50; private final String mPropertyName; private final int mAutoCorkDelayMs; diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index ee9bd3d259fb..7fe29a920931 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -277,6 +277,14 @@ public class IntentFilter implements Parcelable { public static final String SCHEME_HTTPS = "https"; /** + * Package scheme + * + * @see #addDataScheme(String) + * @hide + */ + public static final String SCHEME_PACKAGE = "package"; + + /** * The value to indicate a wildcard for incoming match arguments. * @hide */ diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 043953d1aabd..0c6810c07394 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -1134,6 +1134,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * @hide */ @SystemApi + @TestApi public int targetSandboxVersion; /** diff --git a/core/java/android/content/pm/InstantAppRequest.java b/core/java/android/content/pm/InstantAppRequest.java index 84f5021f0538..5b5d109fb863 100644 --- a/core/java/android/content/pm/InstantAppRequest.java +++ b/core/java/android/content/pm/InstantAppRequest.java @@ -18,6 +18,7 @@ package android.content.pm; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.content.Intent; import android.os.Bundle; @@ -40,7 +41,7 @@ public final class InstantAppRequest { /** Whether or not the requesting package was an instant app */ public final boolean isRequesterInstantApp; /** ID of the user requesting the instant application */ - public final int userId; + public final @UserIdInt int userId; /** * Optional extra bundle provided by the source application to the installer for additional * verification. @@ -60,7 +61,7 @@ public final class InstantAppRequest { public InstantAppRequest(AuxiliaryResolveInfo responseObj, Intent origIntent, String resolvedType, String callingPackage, @Nullable String callingFeatureId, - boolean isRequesterInstantApp, int userId, Bundle verificationBundle, + boolean isRequesterInstantApp, @UserIdInt int userId, Bundle verificationBundle, boolean resolveForStart, @Nullable int[] hostDigestPrefixSecure, @NonNull String token) { this.responseObj = responseObj; diff --git a/core/java/android/content/pm/IntentFilterVerificationInfo.java b/core/java/android/content/pm/IntentFilterVerificationInfo.java index 67bda2ce3944..0a913acba9f5 100644 --- a/core/java/android/content/pm/IntentFilterVerificationInfo.java +++ b/core/java/android/content/pm/IntentFilterVerificationInfo.java @@ -56,19 +56,19 @@ public final class IntentFilterVerificationInfo implements Parcelable { private ArraySet<String> mDomains = new ArraySet<>(); private String mPackageName; - private int mMainStatus; + private int mStatus; /** @hide */ public IntentFilterVerificationInfo() { mPackageName = null; - mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; + mStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; } /** @hide */ public IntentFilterVerificationInfo(String packageName, ArraySet<String> domains) { mPackageName = packageName; mDomains = domains; - mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; + mStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; } /** @hide */ @@ -87,14 +87,14 @@ public final class IntentFilterVerificationInfo implements Parcelable { } public int getStatus() { - return mMainStatus; + return mStatus; } /** @hide */ public void setStatus(int s) { if (s >= INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED && s <= INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) { - mMainStatus = s; + mStatus = s; } else { Log.w(TAG, "Trying to set a non supported status: " + s); } @@ -156,7 +156,7 @@ public final class IntentFilterVerificationInfo implements Parcelable { if (status == -1) { Log.e(TAG, "Unknown status value: " + status); } - mMainStatus = status; + mStatus = status; int outerDepth = parser.getDepth(); int type; @@ -184,7 +184,7 @@ public final class IntentFilterVerificationInfo implements Parcelable { /** @hide */ public void writeToXml(XmlSerializer serializer) throws IOException { serializer.attribute(null, ATTR_PACKAGE_NAME, mPackageName); - serializer.attribute(null, ATTR_STATUS, String.valueOf(mMainStatus)); + serializer.attribute(null, ATTR_STATUS, String.valueOf(mStatus)); for (String str : mDomains) { serializer.startTag(null, TAG_DOMAIN); serializer.attribute(null, ATTR_DOMAIN_NAME, str); @@ -194,7 +194,7 @@ public final class IntentFilterVerificationInfo implements Parcelable { /** @hide */ public String getStatusString() { - return getStatusStringFromValue(((long)mMainStatus) << 32); + return getStatusStringFromValue(((long) mStatus) << 32); } /** @hide */ @@ -233,7 +233,7 @@ public final class IntentFilterVerificationInfo implements Parcelable { private void readFromParcel(Parcel source) { mPackageName = source.readString(); - mMainStatus = source.readInt(); + mStatus = source.readInt(); ArrayList<String> list = new ArrayList<>(); source.readStringList(list); mDomains.addAll(list); @@ -242,7 +242,7 @@ public final class IntentFilterVerificationInfo implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(mPackageName); - dest.writeInt(mMainStatus); + dest.writeInt(mStatus); dest.writeStringList(new ArrayList<>(mDomains)); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index e08af5534afd..7b2955db3318 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3373,6 +3373,7 @@ public abstract class PackageManager { * @hide */ @SystemApi + @TestApi public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 1 << 5; /** diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java index a605f5d68f06..f86eb9082e01 100644 --- a/core/java/android/hardware/biometrics/BiometricManager.java +++ b/core/java/android/hardware/biometrics/BiometricManager.java @@ -300,26 +300,6 @@ public class BiometricManager { } /** - * Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password) - * - * @param userId this operation takes effect for. - * @param hardwareAuthToken an opaque token returned by password confirmation. - * @hide - */ - @RequiresPermission(USE_BIOMETRIC_INTERNAL) - public void resetLockout(int userId, byte[] hardwareAuthToken) { - if (mService != null) { - try { - mService.resetLockout(userId, hardwareAuthToken); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } else { - Slog.w(TAG, "resetLockout(): Service not connected"); - } - } - - /** * Get a list of AuthenticatorIDs for biometric authenticators which have 1) enrolled templates, * and 2) meet the requirements for integrating with Keystore. The AuthenticatorIDs are known * in Keystore land as SIDs, and are used during key generation. diff --git a/core/java/android/hardware/biometrics/IAuthService.aidl b/core/java/android/hardware/biometrics/IAuthService.aidl index c1d0ad44850d..dd6aa736a1a3 100644 --- a/core/java/android/hardware/biometrics/IAuthService.aidl +++ b/core/java/android/hardware/biometrics/IAuthService.aidl @@ -46,9 +46,6 @@ interface IAuthService { // Register callback for when keyguard biometric eligibility changes. void registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback); - // Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password) - void resetLockout(int userId, in byte [] hardwareAuthToken); - // Get a list of AuthenticatorIDs for authenticators which have enrolled templates and meet // the requirements for integrating with Keystore. The AuthenticatorID are known in Keystore // land as SIDs, and are used during key generation. diff --git a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl index 8eb22dabbf3c..5e6fe6885f9d 100644 --- a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl +++ b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl @@ -53,9 +53,6 @@ interface IBiometricAuthenticator { // Return the LockoutTracker status for the specified user int getLockoutModeForUser(int userId); - // Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password) - void resetLockout(int userId, in byte [] hardwareAuthToken); - // Gets the authenticator ID representing the current set of enrolled templates long getAuthenticatorId(int callingUserId); } diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl index a5b3abb30cbb..005ed324da77 100644 --- a/core/java/android/hardware/biometrics/IBiometricService.aidl +++ b/core/java/android/hardware/biometrics/IBiometricService.aidl @@ -56,9 +56,6 @@ interface IBiometricService { // Client lifecycle is still managed in <Biometric>Service. void onReadyForAuthentication(int cookie); - // Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password) - void resetLockout(int userId, in byte [] hardwareAuthToken); - // Get a list of AuthenticatorIDs for authenticators which have enrolled templates and meet // the requirements for integrating with Keystore. The AuthenticatorID are known in Keystore // land as SIDs, and are used during key generation. diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java index 19cb13c7e114..1b114d3528a2 100644 --- a/core/java/android/hardware/face/FaceManager.java +++ b/core/java/android/hardware/face/FaceManager.java @@ -72,6 +72,8 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan private static final int MSG_SET_FEATURE_COMPLETED = 107; private static final int MSG_CHALLENGE_GENERATED = 108; private static final int MSG_FACE_DETECTED = 109; + private static final int MSG_CHALLENGE_INTERRUPTED = 110; + private static final int MSG_CHALLENGE_INTERRUPT_FINISHED = 111; private final IFaceService mService; private final Context mContext; @@ -141,14 +143,19 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan } @Override - public void onChallengeGenerated(long challenge) { - if (mGenerateChallengeCallback instanceof InternalGenerateChallengeCallback) { - // Perform this on system_server thread, since the application's thread is - // blocked waiting for the result - mGenerateChallengeCallback.onGenerateChallengeResult(challenge); - } else { - mHandler.obtainMessage(MSG_CHALLENGE_GENERATED, challenge).sendToTarget(); - } + public void onChallengeGenerated(int sensorId, long challenge) { + mHandler.obtainMessage(MSG_CHALLENGE_GENERATED, sensorId, 0, challenge) + .sendToTarget(); + } + + @Override + public void onChallengeInterrupted(int sensorId) { + mHandler.obtainMessage(MSG_CHALLENGE_INTERRUPTED, sensorId).sendToTarget(); + } + + @Override + public void onChallengeInterruptFinished(int sensorId) { + mHandler.obtainMessage(MSG_CHALLENGE_INTERRUPT_FINISHED, sensorId).sendToTarget(); } }; @@ -405,35 +412,6 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan } /** - * Same as {@link #generateChallenge(GenerateChallengeCallback)}, except blocks until the - * TEE/hardware operation is complete. - * @return challenge generated in the TEE/hardware - * @hide - */ - @RequiresPermission(MANAGE_BIOMETRIC) - public long generateChallengeBlocking() { - final AtomicReference<Long> result = new AtomicReference<>(); - final CountDownLatch latch = new CountDownLatch(1); - final GenerateChallengeCallback callback = new InternalGenerateChallengeCallback() { - @Override - public void onGenerateChallengeResult(long challenge) { - result.set(challenge); - latch.countDown(); - } - }; - - generateChallenge(callback); - - try { - latch.await(1, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Slog.e(TAG, "Interrupted while generatingChallenge", e); - e.printStackTrace(); - } - return result.get(); - } - - /** * Generates a unique random challenge in the TEE. A typical use case is to have it wrapped in a * HardwareAuthenticationToken, minted by Gatekeeper upon PIN/Pattern/Password verification. * The HardwareAuthenticationToken can then be sent to the biometric HAL together with a @@ -446,11 +424,12 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan * @hide */ @RequiresPermission(MANAGE_BIOMETRIC) - public void generateChallenge(GenerateChallengeCallback callback) { + public void generateChallenge(int sensorId, GenerateChallengeCallback callback) { if (mService != null) { try { mGenerateChallengeCallback = callback; - mService.generateChallenge(mToken, mServiceReceiver, mContext.getOpPackageName()); + mService.generateChallenge(mToken, sensorId, mServiceReceiver, + mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -458,15 +437,66 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan } /** - * Invalidates the current auth token. + * Same as {@link #generateChallenge(int, GenerateChallengeCallback)}, but assumes the first + * enumerated sensor. + * @hide + */ + @RequiresPermission(MANAGE_BIOMETRIC) + public void generateChallenge(GenerateChallengeCallback callback) { + final List<FaceSensorProperties> faceSensorProperties = getSensorProperties(); + if (faceSensorProperties.isEmpty()) { + Slog.e(TAG, "No sensors"); + return; + } + + final int sensorId = faceSensorProperties.get(0).sensorId; + generateChallenge(sensorId, callback); + } + + /** + * Invalidates the current challenge. * * @hide */ @RequiresPermission(MANAGE_BIOMETRIC) public void revokeChallenge() { + final List<FaceSensorProperties> faceSensorProperties = getSensorProperties(); + if (faceSensorProperties.isEmpty()) { + Slog.e(TAG, "No sensors during revokeChallenge"); + } + revokeChallenge(faceSensorProperties.get(0).sensorId); + } + + /** + * Invalidates the current challenge. + * + * @hide + */ + @RequiresPermission(MANAGE_BIOMETRIC) + public void revokeChallenge(int sensorId) { if (mService != null) { try { - mService.revokeChallenge(mToken, mContext.getOpPackageName()); + mService.revokeChallenge(mToken, sensorId, mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + + /** + * Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password) + * + * @param sensorId Sensor ID that this operation takes effect for + * @param userId User ID that this operation takes effect for. + * @param hardwareAuthToken An opaque token returned by password confirmation. + * @hide + */ + @RequiresPermission(USE_BIOMETRIC_INTERNAL) + public void resetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken) { + if (mService != null) { + try { + mService.resetLockout(mToken, sensorId, userId, hardwareAuthToken, + mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1071,14 +1101,26 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan } /** + * Callback structure provided to {@link #generateChallenge(int, GenerateChallengeCallback)}. * @hide */ public interface GenerateChallengeCallback { - void onGenerateChallengeResult(long challenge); - } + /** + * Invoked when a challenge has been generated. + */ + void onGenerateChallengeResult(int sensorId, long challenge); - private abstract static class InternalGenerateChallengeCallback - implements GenerateChallengeCallback {} + /** + * Invoked if the challenge has not been revoked and a subsequent caller/owner invokes + * {@link #generateChallenge(int, GenerateChallengeCallback)}, but + */ + default void onChallengeInterrupted(int sensorId) {} + + /** + * Invoked when the interrupting client has finished (e.g. revoked its challenge). + */ + default void onChallengeInterruptFinished(int sensorId) {} + } private class OnEnrollCancelListener implements OnCancelListener { @Override @@ -1151,12 +1193,18 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan args.recycle(); break; case MSG_CHALLENGE_GENERATED: - sendChallengeGenerated((long) msg.obj /* challenge */); + sendChallengeGenerated(msg.arg1 /* sensorId */, (long) msg.obj /* challenge */); break; case MSG_FACE_DETECTED: sendFaceDetected(msg.arg1 /* sensorId */, msg.arg2 /* userId */, (boolean) msg.obj /* isStrongBiometric */); break; + case MSG_CHALLENGE_INTERRUPTED: + sendChallengeInterrupted((int) msg.obj /* sensorId */); + break; + case MSG_CHALLENGE_INTERRUPT_FINISHED: + sendChallengeInterruptFinished((int) msg.obj /* sensorId */); + break; default: Slog.w(TAG, "Unknown message: " + msg.what); } @@ -1178,11 +1226,11 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan mGetFeatureCallback.onCompleted(success, feature, value); } - private void sendChallengeGenerated(long challenge) { + private void sendChallengeGenerated(int sensorId, long challenge) { if (mGenerateChallengeCallback == null) { return; } - mGenerateChallengeCallback.onGenerateChallengeResult(challenge); + mGenerateChallengeCallback.onGenerateChallengeResult(sensorId, challenge); } private void sendFaceDetected(int sensorId, int userId, boolean isStrongBiometric) { @@ -1193,6 +1241,22 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan mFaceDetectionCallback.onFaceDetected(sensorId, userId, isStrongBiometric); } + private void sendChallengeInterrupted(int sensorId) { + if (mGenerateChallengeCallback == null) { + Slog.e(TAG, "sendChallengeInterrupted, callback null"); + return; + } + mGenerateChallengeCallback.onChallengeInterrupted(sensorId); + } + + private void sendChallengeInterruptFinished(int sensorId) { + if (mGenerateChallengeCallback == null) { + Slog.e(TAG, "sendChallengeInterruptFinished, callback null"); + return; + } + mGenerateChallengeCallback.onChallengeInterruptFinished(sensorId); + } + private void sendRemovedResult(Face face, int remaining) { if (mRemovalCallback == null) { return; diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl index a9097d401349..437feb13b845 100644 --- a/core/java/android/hardware/face/IFaceService.aidl +++ b/core/java/android/hardware/face/IFaceService.aidl @@ -83,10 +83,10 @@ interface IFaceService { boolean isHardwareDetected(String opPackageName); // Get a pre-enrollment authentication token - void generateChallenge(IBinder token, IFaceServiceReceiver receiver, String opPackageName); + void generateChallenge(IBinder token, int sensorId, IFaceServiceReceiver receiver, String opPackageName); // Finish an enrollment sequence and invalidate the authentication token - void revokeChallenge(IBinder token, String opPackageName); + void revokeChallenge(IBinder token, int sensorId, String opPackageName); // Determine if a user has at least one enrolled face boolean hasEnrolledFaces(int userId, String opPackageName); @@ -98,7 +98,7 @@ interface IFaceService { long getAuthenticatorId(int callingUserId); // Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password) - void resetLockout(int userId, in byte [] hardwareAuthToken); + void resetLockout(IBinder token, int sensorId, int userId, in byte [] hardwareAuthToken, String opPackageName); // Add a callback which gets notified when the face lockout period expired. void addLockoutResetCallback(IBiometricServiceLockoutResetCallback callback, String opPackageName); diff --git a/core/java/android/hardware/face/IFaceServiceReceiver.aidl b/core/java/android/hardware/face/IFaceServiceReceiver.aidl index 2600b7def03a..bd4d3a0b7017 100644 --- a/core/java/android/hardware/face/IFaceServiceReceiver.aidl +++ b/core/java/android/hardware/face/IFaceServiceReceiver.aidl @@ -31,5 +31,7 @@ oneway interface IFaceServiceReceiver { void onRemoved(in Face face, int remaining); void onFeatureSet(boolean success, int feature); void onFeatureGet(boolean success, int feature, boolean value); - void onChallengeGenerated(long challenge); + void onChallengeGenerated(int sensorId, long challenge); + void onChallengeInterrupted(int sensorId); + void onChallengeInterruptFinished(int sensorId); } diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 71598eb6394f..c12bb39c3175 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -18,6 +18,7 @@ package android.hardware.fingerprint; import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.Manifest.permission.MANAGE_FINGERPRINT; +import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT; import static android.Manifest.permission.USE_BIOMETRIC; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import static android.Manifest.permission.USE_FINGERPRINT; @@ -378,12 +379,9 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * @hide */ public interface GenerateChallengeCallback { - void onChallengeGenerated(long challenge); + void onChallengeGenerated(int sensorId, long challenge); } - private abstract static class InternalGenerateChallengeCallback - implements GenerateChallengeCallback {} - /** * Request authentication of a crypto object. This call warms up the fingerprint hardware * and starts scanning for a fingerprint. It terminates when @@ -593,16 +591,34 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * @hide */ @RequiresPermission(MANAGE_FINGERPRINT) - public void generateChallenge(GenerateChallengeCallback callback) { + public void generateChallenge(int sensorId, GenerateChallengeCallback callback) { if (mService != null) try { mGenerateChallengeCallback = callback; - mService.generateChallenge(mToken, mServiceReceiver, mContext.getOpPackageName()); + mService.generateChallenge(mToken, sensorId, mServiceReceiver, + mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** + * Same as {@link #generateChallenge(int, GenerateChallengeCallback)}, but assumes the first + * enumerated sensor. + * @hide + */ + @RequiresPermission(MANAGE_FINGERPRINT) + public void generateChallenge(GenerateChallengeCallback callback) { + final List<FingerprintSensorProperties> fingerprintSensorProperties = getSensorProperties(); + if (fingerprintSensorProperties.isEmpty()) { + Slog.e(TAG, "No sensors"); + return; + } + + final int sensorId = fingerprintSensorProperties.get(0).sensorId; + generateChallenge(sensorId, callback); + } + + /** * Finishes enrollment and cancels the current auth token. * @hide */ @@ -616,6 +632,26 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } /** + * Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password) + * + * @param sensorId Sensor ID that this operation takes effect for + * @param userId User ID that this operation takes effect for. + * @param hardwareAuthToken An opaque token returned by password confirmation. + * @hide + */ + @RequiresPermission(RESET_FINGERPRINT_LOCKOUT) + public void resetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken) { + if (mService != null) { + try { + mService.resetLockout(mToken, sensorId, userId, hardwareAuthToken, + mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + + /** * Remove given fingerprint template from fingerprint hardware and/or protected storage. * @param fp the fingerprint item to remove * @param userId the user who this fingerprint belongs to @@ -901,7 +937,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing sendRemovedResult((Fingerprint) msg.obj, msg.arg1 /* remaining */); break; case MSG_CHALLENGE_GENERATED: - sendChallengeGenerated((long) msg.obj /* challenge */); + sendChallengeGenerated(msg.arg1 /* sensorId */, (long) msg.obj /* challenge */); break; case MSG_FINGERPRINT_DETECTED: sendFingerprintDetected(msg.arg1 /* sensorId */, msg.arg2 /* userId */, @@ -989,12 +1025,12 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } } - private void sendChallengeGenerated(long challenge) { + private void sendChallengeGenerated(int sensorId, long challenge) { if (mGenerateChallengeCallback == null) { Slog.e(TAG, "sendChallengeGenerated, callback null"); return; } - mGenerateChallengeCallback.onChallengeGenerated(challenge); + mGenerateChallengeCallback.onChallengeGenerated(sensorId, challenge); } private void sendFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric) { @@ -1178,14 +1214,9 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } @Override // binder call - public void onChallengeGenerated(long challenge) { - if (mGenerateChallengeCallback instanceof InternalGenerateChallengeCallback) { - // Perform this on system_server thread, since the application's thread is - // blocked waiting for the result - mGenerateChallengeCallback.onChallengeGenerated(challenge); - } else { - mHandler.obtainMessage(MSG_CHALLENGE_GENERATED, challenge).sendToTarget(); - } + public void onChallengeGenerated(int sensorId, long challenge) { + mHandler.obtainMessage(MSG_CHALLENGE_GENERATED, sensorId, 0, challenge) + .sendToTarget(); } }; diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java b/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java index a774121c43f4..b28551c52b9e 100644 --- a/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java +++ b/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java @@ -45,18 +45,24 @@ public class FingerprintSensorProperties implements Parcelable { public final int sensorId; public final @SensorType int sensorType; + // IBiometricsFingerprint@2.1 does not manage timeout below the HAL, so the Gatekeeper HAT + // cannot be checked + public final boolean resetLockoutRequiresHardwareAuthToken; /** * Initializes SensorProperties with specified values */ - public FingerprintSensorProperties(int sensorId, @SensorType int sensorType) { + public FingerprintSensorProperties(int sensorId, @SensorType int sensorType, + boolean resetLockoutRequiresHardwareAuthToken) { this.sensorId = sensorId; this.sensorType = sensorType; + this.resetLockoutRequiresHardwareAuthToken = resetLockoutRequiresHardwareAuthToken; } protected FingerprintSensorProperties(Parcel in) { sensorId = in.readInt(); sensorType = in.readInt(); + resetLockoutRequiresHardwareAuthToken = in.readBoolean(); } public static final Creator<FingerprintSensorProperties> CREATOR = @@ -81,5 +87,6 @@ public class FingerprintSensorProperties implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeInt(sensorId); dest.writeInt(sensorType); + dest.writeBoolean(resetLockoutRequiresHardwareAuthToken); } } diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index f6069d81934f..0fae15648e15 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -88,7 +88,7 @@ interface IFingerprintService { boolean isHardwareDetected(String opPackageName); // Get a pre-enrollment authentication token - void generateChallenge(IBinder token, IFingerprintServiceReceiver receiver, String opPackageName); + void generateChallenge(IBinder token, int sensorId, IFingerprintServiceReceiver receiver, String opPackageName); // Finish an enrollment sequence and invalidate the authentication token void revokeChallenge(IBinder token, String opPackageName); @@ -103,7 +103,7 @@ interface IFingerprintService { long getAuthenticatorId(int callingUserId); // Reset the timeout when user authenticates with strong auth (e.g. PIN, pattern or password) - void resetLockout(int userId, in byte [] hardwareAuthToken); + void resetLockout(IBinder token, int sensorId, int userId, in byte[] hardwareAuthToken, String opPackageNAame); // Add a callback which gets notified when the fingerprint lockout period expired. void addLockoutResetCallback(IBiometricServiceLockoutResetCallback callback, String opPackageName); diff --git a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl index ad8fbc087ed0..095b8e9527ad 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl @@ -29,5 +29,5 @@ oneway interface IFingerprintServiceReceiver { void onAuthenticationFailed(); void onError(int error, int vendorCode); void onRemoved(in Fingerprint fp, int remaining); - void onChallengeGenerated(long challenge); + void onChallengeGenerated(int sensorId, long challenge); } diff --git a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl index 32530da74e89..a57726c4afe4 100644 --- a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl +++ b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl @@ -25,4 +25,7 @@ oneway interface IUdfpsOverlayController { // Hides the overlay. void hideUdfpsOverlay(); + + // Shows debug messages on the UDFPS overlay. + void setDebugMessage(String message); } diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index a6b869d19867..1eb3fc11df7b 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -64,10 +64,11 @@ public class GraphicsEnvironment { private static final String SYSTEM_DRIVER_NAME = "system"; private static final String SYSTEM_DRIVER_VERSION_NAME = ""; private static final long SYSTEM_DRIVER_VERSION_CODE = 0; - private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0"; + private static final String PROPERTY_GFX_DRIVER_PRODUCTION = "ro.gfx.driver.0"; private static final String PROPERTY_GFX_DRIVER_PRERELEASE = "ro.gfx.driver.1"; private static final String PROPERTY_GFX_DRIVER_BUILD_TIME = "ro.gfx.driver_build_time"; - private static final String METADATA_DRIVER_BUILD_TIME = "com.android.gamedriver.build_time"; + private static final String METADATA_DRIVER_BUILD_TIME = + "com.android.graphics.updatabledriver.build_time"; private static final String METADATA_DEVELOPER_DRIVER_ENABLE = "com.android.graphics.developerdriver.enable"; private static final String METADATA_INJECT_LAYERS_ENABLE = @@ -78,20 +79,20 @@ public class GraphicsEnvironment { private static final String ACTION_ANGLE_FOR_ANDROID_TOAST_MESSAGE = "android.app.action.ANGLE_FOR_ANDROID_TOAST_MESSAGE"; private static final String INTENT_KEY_A4A_TOAST_MESSAGE = "A4A Toast Message"; - private static final String GAME_DRIVER_ALLOWLIST_ALL = "*"; - private static final String GAME_DRIVER_SPHAL_LIBRARIES_FILENAME = "sphal_libraries.txt"; + private static final String UPDATABLE_DRIVER_ALLOWLIST_ALL = "*"; + private static final String UPDATABLE_DRIVER_SPHAL_LIBRARIES_FILENAME = "sphal_libraries.txt"; private static final int VULKAN_1_0 = 0x00400000; private static final int VULKAN_1_1 = 0x00401000; - // GAME_DRIVER_ALL_APPS + // UPDATABLE_DRIVER_ALL_APPS // 0: Default (Invalid values fallback to default as well) - // 1: All apps use Game Driver - // 2: All apps use Prerelease Driver + // 1: All apps use updatable production driver + // 2: All apps use updatable prerelease driver // 3: All apps use system graphics driver - private static final int GAME_DRIVER_GLOBAL_OPT_IN_DEFAULT = 0; - private static final int GAME_DRIVER_GLOBAL_OPT_IN_GAME_DRIVER = 1; - private static final int GAME_DRIVER_GLOBAL_OPT_IN_PRERELEASE_DRIVER = 2; - private static final int GAME_DRIVER_GLOBAL_OPT_IN_OFF = 3; + private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_DEFAULT = 0; + private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_PRODUCTION_DRIVER = 1; + private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_PRERELEASE_DRIVER = 2; + private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_OFF = 3; private ClassLoader mClassLoader; private String mLibrarySearchPaths; @@ -722,14 +723,17 @@ public class GraphicsEnvironment { * Return the driver package name to use. Return null for system driver. */ private static String chooseDriverInternal(Bundle coreSettings, ApplicationInfo ai) { - final String gameDriver = SystemProperties.get(PROPERTY_GFX_DRIVER); - final boolean hasGameDriver = gameDriver != null && !gameDriver.isEmpty(); + final String productionDriver = SystemProperties.get(PROPERTY_GFX_DRIVER_PRODUCTION); + final boolean hasProductionDriver = productionDriver != null && !productionDriver.isEmpty(); final String prereleaseDriver = SystemProperties.get(PROPERTY_GFX_DRIVER_PRERELEASE); final boolean hasPrereleaseDriver = prereleaseDriver != null && !prereleaseDriver.isEmpty(); - if (!hasGameDriver && !hasPrereleaseDriver) { - if (DEBUG) Log.v(TAG, "Neither Game Driver nor prerelease driver is supported."); + if (!hasProductionDriver && !hasPrereleaseDriver) { + if (DEBUG) { + Log.v(TAG, + "Neither updatable production driver nor prerelease driver is supported."); + } return null; } @@ -745,56 +749,59 @@ public class GraphicsEnvironment { (ai.metaData != null && ai.metaData.getBoolean(METADATA_DEVELOPER_DRIVER_ENABLE)) || isDebuggable(); - // Priority for Game Driver settings global on confliction (Higher priority comes first): - // 1. GAME_DRIVER_ALL_APPS - // 2. GAME_DRIVER_OPT_OUT_APPS - // 3. GAME_DRIVER_PRERELEASE_OPT_IN_APPS - // 4. GAME_DRIVER_OPT_IN_APPS - // 5. GAME_DRIVER_DENYLIST - // 6. GAME_DRIVER_ALLOWLIST - switch (coreSettings.getInt(Settings.Global.GAME_DRIVER_ALL_APPS, 0)) { - case GAME_DRIVER_GLOBAL_OPT_IN_OFF: - if (DEBUG) Log.v(TAG, "Game Driver is turned off on this device."); + // Priority of updatable driver settings on confliction (Higher priority comes first): + // 1. UPDATABLE_DRIVER_ALL_APPS + // 2. UPDATABLE_DRIVER_PRODUCTION_OPT_OUT_APPS + // 3. UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS + // 4. UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS + // 5. UPDATABLE_DRIVER_PRODUCTION_DENYLIST + // 6. UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST + switch (coreSettings.getInt(Settings.Global.UPDATABLE_DRIVER_ALL_APPS, 0)) { + case UPDATABLE_DRIVER_GLOBAL_OPT_IN_OFF: + if (DEBUG) Log.v(TAG, "updatable driver is turned off on this device."); return null; - case GAME_DRIVER_GLOBAL_OPT_IN_GAME_DRIVER: - if (DEBUG) Log.v(TAG, "All apps opt in to use Game Driver."); - return hasGameDriver ? gameDriver : null; - case GAME_DRIVER_GLOBAL_OPT_IN_PRERELEASE_DRIVER: - if (DEBUG) Log.v(TAG, "All apps opt in to use prerelease driver."); + case UPDATABLE_DRIVER_GLOBAL_OPT_IN_PRODUCTION_DRIVER: + if (DEBUG) Log.v(TAG, "All apps opt in to use updatable production driver."); + return hasProductionDriver ? productionDriver : null; + case UPDATABLE_DRIVER_GLOBAL_OPT_IN_PRERELEASE_DRIVER: + if (DEBUG) Log.v(TAG, "All apps opt in to use updatable prerelease driver."); return hasPrereleaseDriver && enablePrereleaseDriver ? prereleaseDriver : null; - case GAME_DRIVER_GLOBAL_OPT_IN_DEFAULT: + case UPDATABLE_DRIVER_GLOBAL_OPT_IN_DEFAULT: default: break; } final String appPackageName = ai.packageName; - if (getGlobalSettingsString(null, coreSettings, Settings.Global.GAME_DRIVER_OPT_OUT_APPS) + if (getGlobalSettingsString(null, coreSettings, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_OUT_APPS) .contains(appPackageName)) { - if (DEBUG) Log.v(TAG, "App opts out for Game Driver."); + if (DEBUG) Log.v(TAG, "App opts out for updatable production driver."); return null; } if (getGlobalSettingsString( - null, coreSettings, Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS) + null, coreSettings, Settings.Global.UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS) .contains(appPackageName)) { - if (DEBUG) Log.v(TAG, "App opts in for prerelease Game Driver."); + if (DEBUG) Log.v(TAG, "App opts in for updatable prerelease driver."); return hasPrereleaseDriver && enablePrereleaseDriver ? prereleaseDriver : null; } - // Early return here since the rest logic is only for Game Driver. - if (!hasGameDriver) { - if (DEBUG) Log.v(TAG, "Game Driver is not supported on the device."); + // Early return here since the rest logic is only for updatable production Driver. + if (!hasProductionDriver) { + if (DEBUG) Log.v(TAG, "Updatable production driver is not supported on the device."); return null; } final boolean isOptIn = - getGlobalSettingsString(null, coreSettings, Settings.Global.GAME_DRIVER_OPT_IN_APPS) + getGlobalSettingsString(null, coreSettings, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS) .contains(appPackageName); final List<String> allowlist = - getGlobalSettingsString(null, coreSettings, Settings.Global.GAME_DRIVER_ALLOWLIST); - if (!isOptIn && allowlist.indexOf(GAME_DRIVER_ALLOWLIST_ALL) != 0 + getGlobalSettingsString(null, coreSettings, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST); + if (!isOptIn && allowlist.indexOf(UPDATABLE_DRIVER_ALLOWLIST_ALL) != 0 && !allowlist.contains(appPackageName)) { - if (DEBUG) Log.v(TAG, "App is not on the allowlist for Game Driver."); + if (DEBUG) Log.v(TAG, "App is not on the allowlist for updatable production driver."); return null; } @@ -802,13 +809,13 @@ public class GraphicsEnvironment { // terminate early if it's on the denylist and fallback to system driver. if (!isOptIn && getGlobalSettingsString( - null, coreSettings, Settings.Global.GAME_DRIVER_DENYLIST) + null, coreSettings, Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLIST) .contains(appPackageName)) { - if (DEBUG) Log.v(TAG, "App is on the denylist for Game Driver."); + if (DEBUG) Log.v(TAG, "App is on the denylist for updatable production driver."); return null; } - return gameDriver; + return productionDriver; } /** @@ -873,7 +880,7 @@ public class GraphicsEnvironment { final String driverBuildTime = driverAppInfo.metaData.getString(METADATA_DRIVER_BUILD_TIME); if (driverBuildTime == null || driverBuildTime.isEmpty()) { - throw new IllegalArgumentException("com.android.gamedriver.build_time is not set"); + Log.v(TAG, "com.android.graphics.updatabledriver.build_time is not set"); } // driver_build_time in the meta-data is in "L<Unix epoch timestamp>" format. e.g. L123456. // Long.parseLong will throw if the meta-data "driver_build_time" is not set properly. @@ -901,7 +908,7 @@ public class GraphicsEnvironment { final Context driverContext = context.createPackageContext(driverPackageName, Context.CONTEXT_RESTRICTED); final BufferedReader reader = new BufferedReader(new InputStreamReader( - driverContext.getAssets().open(GAME_DRIVER_SPHAL_LIBRARIES_FILENAME))); + driverContext.getAssets().open(UPDATABLE_DRIVER_SPHAL_LIBRARIES_FILENAME))); final ArrayList<String> assetStrings = new ArrayList<>(); for (String assetString; (assetString = reader.readLine()) != null;) { assetStrings.add(assetString); @@ -913,7 +920,7 @@ public class GraphicsEnvironment { } } catch (IOException e) { if (DEBUG) { - Log.w(TAG, "Failed to load '" + GAME_DRIVER_SPHAL_LIBRARIES_FILENAME + "'"); + Log.w(TAG, "Failed to load '" + UPDATABLE_DRIVER_SPHAL_LIBRARIES_FILENAME + "'"); } } return ""; diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 7ad0e7d337d2..73b33c20d296 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -8316,6 +8316,13 @@ public final class Settings { public static final String PANIC_GESTURE_ENABLED = "panic_gesture_enabled"; /** + * Whether the panic button (emergency sos) sound should be enabled. + * + * @hide + */ + public static final String PANIC_SOUND_ENABLED = "panic_sound_enabled"; + + /** * Whether the camera launch gesture to double tap the power button when the screen is off * should be disabled. * @@ -12355,63 +12362,71 @@ public final class Settings { "show_angle_in_use_dialog_box"; /** - * Game Driver global preference for all Apps. + * Updatable driver global preference for all Apps. * 0 = Default - * 1 = All Apps use Game Driver - * 2 = All Apps use system graphics driver + * 1 = All Apps use updatable production driver + * 2 = All apps use updatable prerelease driver + * 3 = All Apps use system graphics driver * @hide */ - public static final String GAME_DRIVER_ALL_APPS = "game_driver_all_apps"; + public static final String UPDATABLE_DRIVER_ALL_APPS = "updatable_driver_all_apps"; /** - * List of Apps selected to use Game Driver. + * List of Apps selected to use updatable production driver. * i.e. <pkg1>,<pkg2>,...,<pkgN> * @hide */ - public static final String GAME_DRIVER_OPT_IN_APPS = "game_driver_opt_in_apps"; + public static final String UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS = + "updatable_driver_production_opt_in_apps"; /** - * List of Apps selected to use prerelease Game Driver. + * List of Apps selected to use updatable prerelease driver. * i.e. <pkg1>,<pkg2>,...,<pkgN> * @hide */ - public static final String GAME_DRIVER_PRERELEASE_OPT_IN_APPS = - "game_driver_prerelease_opt_in_apps"; + public static final String UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS = + "updatable_driver_prerelease_opt_in_apps"; /** - * List of Apps selected not to use Game Driver. + * List of Apps selected not to use updatable production driver. * i.e. <pkg1>,<pkg2>,...,<pkgN> * @hide */ - public static final String GAME_DRIVER_OPT_OUT_APPS = "game_driver_opt_out_apps"; + public static final String UPDATABLE_DRIVER_PRODUCTION_OPT_OUT_APPS = + "updatable_driver_production_opt_out_apps"; /** - * Apps on the denylist that are forbidden to use Game Driver. + * Apps on the denylist that are forbidden to use updatable production driver. * @hide */ - public static final String GAME_DRIVER_DENYLIST = "game_driver_denylist"; + public static final String UPDATABLE_DRIVER_PRODUCTION_DENYLIST = + "updatable_driver_production_denylist"; /** - * List of denylists, each denylist is a denylist for a specific version of Game Driver. + * List of denylists, each denylist is a denylist for a specific version of + * updatable production driver. * @hide */ - public static final String GAME_DRIVER_DENYLISTS = "game_driver_denylists"; + public static final String UPDATABLE_DRIVER_PRODUCTION_DENYLISTS = + "updatable_driver_production_denylists"; /** - * Apps on the allowlist that are allowed to use Game Driver. + * Apps on the allowlist that are allowed to use updatable production driver. * The string is a list of application package names, seperated by comma. * i.e. <apk1>,<apk2>,...,<apkN> * @hide */ - public static final String GAME_DRIVER_ALLOWLIST = "game_driver_allowlist"; + public static final String UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST = + "updatable_driver_production_allowlist"; /** - * List of libraries in sphal accessible by Game Driver + * List of libraries in sphal accessible by updatable driver * The string is a list of library names, separated by colon. * i.e. <lib1>:<lib2>:...:<libN> * @hide */ - public static final String GAME_DRIVER_SPHAL_LIBRARIES = "game_driver_sphal_libraries"; + public static final String UPDATABLE_DRIVER_SPHAL_LIBRARIES = + "updatable_driver_sphal_libraries"; /** * Ordered GPU debug layer list for Vulkan diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java index bf94670e1ca3..6136a80978b7 100644 --- a/core/java/android/view/NotificationHeaderView.java +++ b/core/java/android/view/NotificationHeaderView.java @@ -52,14 +52,12 @@ public class NotificationHeaderView extends ViewGroup { private View mHeaderText; private View mSecondaryHeaderText; private OnClickListener mExpandClickListener; - private OnClickListener mAppOpsListener; private OnClickListener mFeedbackListener; private HeaderTouchListener mTouchListener = new HeaderTouchListener(); private LinearLayout mTransferChip; private NotificationExpandButton mExpandButton; private CachingIconView mIcon; private View mProfileBadge; - private View mAppOps; private View mFeedbackIcon; private boolean mExpanded; private boolean mShowExpandButtonAtEnd; @@ -117,7 +115,6 @@ public class NotificationHeaderView extends ViewGroup { mExpandButton = findViewById(com.android.internal.R.id.expand_button); mIcon = findViewById(com.android.internal.R.id.icon); mProfileBadge = findViewById(com.android.internal.R.id.profile_badge); - mAppOps = findViewById(com.android.internal.R.id.app_ops); mFeedbackIcon = findViewById(com.android.internal.R.id.feedback); } @@ -146,7 +143,6 @@ public class NotificationHeaderView extends ViewGroup { // Icons that should go at the end if ((child == mExpandButton && mShowExpandButtonAtEnd) || child == mProfileBadge - || child == mAppOps || child == mFeedbackIcon || child == mTransferChip) { iconWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth(); @@ -212,7 +208,6 @@ public class NotificationHeaderView extends ViewGroup { // Icons that should go at the end if ((child == mExpandButton && mShowExpandButtonAtEnd) || child == mProfileBadge - || child == mAppOps || child == mFeedbackIcon || child == mTransferChip) { if (end == getMeasuredWidth()) { @@ -282,7 +277,7 @@ public class NotificationHeaderView extends ViewGroup { } private void updateTouchListener() { - if (mExpandClickListener == null && mAppOpsListener == null && mFeedbackListener == null) { + if (mExpandClickListener == null && mFeedbackListener == null) { setOnTouchListener(null); return; } @@ -291,14 +286,6 @@ public class NotificationHeaderView extends ViewGroup { } /** - * Sets onclick listener for app ops icons. - */ - public void setAppOpsOnClickListener(OnClickListener l) { - mAppOpsListener = l; - updateTouchListener(); - } - - /** * Sets onclick listener for feedback icon. */ public void setFeedbackOnClickListener(OnClickListener l) { @@ -394,7 +381,6 @@ public class NotificationHeaderView extends ViewGroup { private final ArrayList<Rect> mTouchRects = new ArrayList<>(); private Rect mExpandButtonRect; - private Rect mAppOpsRect; private Rect mFeedbackRect; private int mTouchSlop; private boolean mTrackGesture; @@ -408,9 +394,7 @@ public class NotificationHeaderView extends ViewGroup { mTouchRects.clear(); addRectAroundView(mIcon); mExpandButtonRect = addRectAroundView(mExpandButton); - mAppOpsRect = addRectAroundView(mAppOps); mFeedbackRect = addRectAroundView(mFeedbackIcon); - setTouchDelegate(new TouchDelegate(mAppOpsRect, mAppOps)); addWidthRect(); mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); } @@ -471,11 +455,7 @@ public class NotificationHeaderView extends ViewGroup { break; case MotionEvent.ACTION_UP: if (mTrackGesture) { - if (mAppOps.isVisibleToUser() && (mAppOpsRect.contains((int) x, (int) y) - || mAppOpsRect.contains((int) mDownX, (int) mDownY))) { - mAppOps.performClick(); - return true; - } else if (mFeedbackIcon.isVisibleToUser() + if (mFeedbackIcon.isVisibleToUser() && (mFeedbackRect.contains((int) x, (int) y)) || mFeedbackRect.contains((int) mDownX, (int) mDownY)) { mFeedbackIcon.performClick(); diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 7923ff0991d8..32ee290a0f47 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -534,7 +534,8 @@ public interface WindowManager extends ViewManager { ScreenshotSource.SCREENSHOT_KEY_OTHER, ScreenshotSource.SCREENSHOT_OVERVIEW, ScreenshotSource.SCREENSHOT_ACCESSIBILITY_ACTIONS, - ScreenshotSource.SCREENSHOT_OTHER}) + ScreenshotSource.SCREENSHOT_OTHER, + ScreenshotSource.SCREENSHOT_VENDOR_GESTURE}) @interface ScreenshotSource { int SCREENSHOT_GLOBAL_ACTIONS = 0; int SCREENSHOT_KEY_CHORD = 1; @@ -542,6 +543,7 @@ public interface WindowManager extends ViewManager { int SCREENSHOT_OVERVIEW = 3; int SCREENSHOT_ACCESSIBILITY_ACTIONS = 4; int SCREENSHOT_OTHER = 5; + int SCREENSHOT_VENDOR_GESTURE = 6; } /** diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java index 3332143251fc..289a36f5380d 100644 --- a/core/java/com/android/internal/widget/ConversationLayout.java +++ b/core/java/com/android/internal/widget/ConversationLayout.java @@ -168,8 +168,6 @@ public class ConversationLayout extends FrameLayout private int mFacePileProtectionWidthExpanded; private boolean mImportantConversation; private TextView mUnreadBadge; - private ViewGroup mAppOps; - private Rect mAppOpsTouchRect = new Rect(); private View mFeedbackIcon; private float mMinTouchSize; private Icon mConversationIcon; @@ -214,7 +212,6 @@ public class ConversationLayout extends FrameLayout mConversationIconView = findViewById(R.id.conversation_icon); mConversationIconContainer = findViewById(R.id.conversation_icon_container); mIcon = findViewById(R.id.icon); - mAppOps = findViewById(com.android.internal.R.id.app_ops); mFeedbackIcon = findViewById(com.android.internal.R.id.feedback); mMinTouchSize = 48 * getResources().getDisplayMetrics().density; mImportanceRingView = findViewById(R.id.conversation_icon_badge_ring); @@ -1174,43 +1171,6 @@ public class ConversationLayout extends FrameLayout }); } mTouchDelegate.clear(); - if (mAppOps.getWidth() > 0) { - - // Let's increase the touch size of the app ops view if it's here - mAppOpsTouchRect.set( - mAppOps.getLeft(), - mAppOps.getTop(), - mAppOps.getRight(), - mAppOps.getBottom()); - for (int i = 0; i < mAppOps.getChildCount(); i++) { - View child = mAppOps.getChildAt(i); - if (child.getVisibility() == GONE) { - continue; - } - // Make sure each child has at least a minTouchSize touch target around it - float childTouchLeft = child.getLeft() + child.getWidth() / 2.0f - - mMinTouchSize / 2.0f; - float childTouchRight = childTouchLeft + mMinTouchSize; - mAppOpsTouchRect.left = (int) Math.min(mAppOpsTouchRect.left, - mAppOps.getLeft() + childTouchLeft); - mAppOpsTouchRect.right = (int) Math.max(mAppOpsTouchRect.right, - mAppOps.getLeft() + childTouchRight); - } - - // Increase the height - int heightIncrease = 0; - if (mAppOpsTouchRect.height() < mMinTouchSize) { - heightIncrease = (int) Math.ceil((mMinTouchSize - mAppOpsTouchRect.height()) - / 2.0f); - } - mAppOpsTouchRect.inset(0, -heightIncrease); - - getRelativeTouchRect(mAppOpsTouchRect, mAppOps); - - // Extend the size of the app opps to be at least 48dp - mTouchDelegate.add(new TouchDelegate(mAppOpsTouchRect, mAppOps)); - - } if (mFeedbackIcon.getVisibility() == VISIBLE) { updateFeedbackIconMargins(); float width = Math.max(mMinTouchSize, mFeedbackIcon.getWidth()); @@ -1240,13 +1200,7 @@ public class ConversationLayout extends FrameLayout private void updateFeedbackIconMargins() { MarginLayoutParams lp = (MarginLayoutParams) mFeedbackIcon.getLayoutParams(); - if (mAppOps.getWidth() == 0) { - lp.setMarginStart(mNotificationHeaderSeparatingMargin); - } else { - float width = Math.max(mMinTouchSize, mFeedbackIcon.getWidth()); - int horizontalMargin = (int) ((width - mFeedbackIcon.getWidth()) / 2); - lp.setMarginStart(horizontalMargin); - } + lp.setMarginStart(mNotificationHeaderSeparatingMargin); mFeedbackIcon.setLayoutParams(lp); } diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index c73441cbd4f9..f96ed36fcedd 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -1790,8 +1790,7 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, #ifdef ANDROID_EXPERIMENTAL_MTE SetTagCheckingLevel(PR_MTE_TCF_SYNC); #endif - // TODO(pcc): Use SYNC here once the allocator supports it. - heap_tagging_level = M_HEAP_TAGGING_LEVEL_ASYNC; + heap_tagging_level = M_HEAP_TAGGING_LEVEL_SYNC; break; default: #ifdef ANDROID_EXPERIMENTAL_MTE diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto index 0d65bd1cf9bb..6eb89040998a 100644 --- a/core/proto/android/app/settings_enums.proto +++ b/core/proto/android/app/settings_enums.proto @@ -2345,10 +2345,10 @@ enum PageId { // OS: Q ZEN_CUSTOM_SETTINGS_DIALOG = 1612; - // OPEN: Settings > Developer Options > Game Driver Preferences + // OPEN: Settings > Developer Options > Graphics Driver Preferences // CATEGORY: SETTINGS // OS: Q - SETTINGS_GAME_DRIVER_DASHBOARD = 1613; + SETTINGS_GRAPHICS_DRIVER_DASHBOARD = 1613; // OPEN: Settings > Accessibility > Vibration > Ring vibration // CATEGORY: SETTINGS diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index e4a142b3335b..d5619ca96fbd 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -433,35 +433,36 @@ message GlobalSettingsProto { // Ordered GPU debug layer list for GLES // i.e. <layer1>:<layer2>:...:<layerN> optional SettingProto debug_layers_gles = 7; - // Game Driver - global preference for all Apps + // Updatable Driver - global preference for all Apps // 0 = Default - // 1 = All Apps use Game Driver - // 2 = All Apps use system graphics driver - optional SettingProto game_driver_all_apps = 8; - // Game Driver - List of Apps selected to use Game Driver + // 1 = All Apps use updatable production driver + // 2 = All apps use updatable prerelease driver + // 3 = All Apps use system graphics driver + optional SettingProto updatable_driver_all_apps = 8; + // Updatable Driver - List of Apps selected to use updatable production driver // i.e. <pkg1>,<pkg2>,...,<pkgN> - optional SettingProto game_driver_opt_in_apps = 9; - // Game Driver - List of Apps selected not to use Game Driver + optional SettingProto updatable_driver_production_opt_in_apps = 9; + // Updatable Driver - List of Apps selected not to use updatable production driver // i.e. <pkg1>,<pkg2>,...,<pkgN> - optional SettingProto game_driver_opt_out_apps = 10; - // Game Driver - List of Apps that are forbidden to use Game Driver - optional SettingProto game_driver_denylist = 11; - // Game Driver - List of Apps that are allowed to use Game Driver - optional SettingProto game_driver_allowlist = 12; + optional SettingProto updatable_driver_production_opt_out_apps = 10; + // Updatable Driver - List of Apps that are forbidden to use updatable production driver + optional SettingProto updatable_driver_production_denylist = 11; + // Updatable Driver - List of Apps that are allowed to use updatable production driver + optional SettingProto updatable_driver_production_allowlist = 12; // ANGLE - List of Apps that can check ANGLE rules optional SettingProto angle_allowlist = 13; - // Game Driver - List of denylists, each denylist is a denylist for - // a specific Game Driver version - optional SettingProto game_driver_denylists = 14; + // Updatable Driver - List of denylists, each denylist is a denylist for + // a specific updatable production driver version + optional SettingProto updatable_driver_production_denylists = 14; // ANGLE - Show a dialog box when ANGLE is selected for the currently running PKG optional SettingProto show_angle_in_use_dialog = 15; - // Game Driver - List of libraries in sphal accessible by Game Driver - optional SettingProto game_driver_sphal_libraries = 16; + // Updatable Driver - List of libraries in sphal accessible by updatable driver + optional SettingProto updatable_driver_sphal_libraries = 16; // ANGLE - External package containing ANGLE libraries optional SettingProto angle_debug_package = 17; - // Game Driver - List of Apps selected to use prerelease Game Driver + // Updatable Driver - List of Apps selected to use updatable prerelease driver // i.e. <pkg1>,<pkg2>,...,<pkgN> - optional SettingProto game_driver_prerelease_opt_in_apps = 18; + optional SettingProto updatable_driver_prerelease_opt_in_apps = 18; } optional Gpu gpu = 59; diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index ca4dc18689bc..541e018d079b 100644 --- a/core/proto/android/providers/settings/secure.proto +++ b/core/proto/android/providers/settings/secure.proto @@ -211,6 +211,7 @@ message SecureSettingsProto { message EmergencyResponse { optional SettingProto panic_gesture_enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto panic_sound_enabled = 2 [ (android.privacy).dest = DEST_AUTOMATIC ]; } optional EmergencyResponse emergency_response = 83; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index edb972730f69..32c1e4a1411c 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -558,6 +558,7 @@ <protected-broadcast android:name="android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED" /> <protected-broadcast android:name="android.app.action.NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED" /> <protected-broadcast android:name="android.app.action.NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED" /> + <protected-broadcast android:name="android.app.action.NOTIFICATION_LISTENER_ENABLED_CHANGED" /> <protected-broadcast android:name="android.app.action.APP_BLOCK_STATE_CHANGED" /> <protected-broadcast android:name="android.permission.GET_APP_GRANTED_URI_PERMISSIONS" /> diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml index d22a19faa52b..9a1b592c895a 100644 --- a/core/res/res/layout/notification_template_header.xml +++ b/core/res/res/layout/notification_template_header.xml @@ -160,43 +160,6 @@ android:visibility="gone" android:contentDescription="@string/notification_work_profile_content_description" /> - <LinearLayout - android:id="@+id/app_ops" - android:layout_height="match_parent" - android:layout_width="wrap_content" - android:layout_marginStart="6dp" - android:background="?android:selectableItemBackgroundBorderless" - android:orientation="horizontal"> - <ImageView - android:id="@+id/camera" - android:layout_width="?attr/notificationHeaderIconSize" - android:layout_height="?attr/notificationHeaderIconSize" - android:src="@drawable/ic_camera" - android:visibility="gone" - android:focusable="false" - android:contentDescription="@string/notification_appops_camera_active" - /> - <ImageView - android:id="@+id/mic" - android:layout_width="?attr/notificationHeaderIconSize" - android:layout_height="?attr/notificationHeaderIconSize" - android:src="@drawable/ic_mic" - android:layout_marginStart="4dp" - android:visibility="gone" - android:focusable="false" - android:contentDescription="@string/notification_appops_microphone_active" - /> - <ImageView - android:id="@+id/overlay" - android:layout_width="?attr/notificationHeaderIconSize" - android:layout_height="?attr/notificationHeaderIconSize" - android:src="@drawable/ic_alert_window_layer" - android:layout_marginStart="4dp" - android:visibility="gone" - android:focusable="false" - android:contentDescription="@string/notification_appops_overlay_active" - /> - </LinearLayout> <include layout="@layout/notification_material_media_transfer_action" android:id="@+id/media_seamless" diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index d0ed635e69a8..bad330e75864 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -983,9 +983,9 @@ <string name="menu_space_shortcut_label" msgid="5949311515646872071">"স্পেচ"</string> <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"লিখক"</string> <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"মচক"</string> - <string name="search_go" msgid="2141477624421347086">"অনুসন্ধান কৰক"</string> + <string name="search_go" msgid="2141477624421347086">"Search"</string> <string name="search_hint" msgid="455364685740251925">"অনুসন্ধান কৰক…"</string> - <string name="searchview_description_search" msgid="1045552007537359343">"অনুসন্ধান কৰক"</string> + <string name="searchview_description_search" msgid="1045552007537359343">"Search"</string> <string name="searchview_description_query" msgid="7430242366971716338">"প্ৰশ্নৰ সন্ধান কৰক"</string> <string name="searchview_description_clear" msgid="1989371719192982900">"প্ৰশ্ন মচক"</string> <string name="searchview_description_submit" msgid="6771060386117334686">"প্ৰশ্ন দাখিল কৰক"</string> @@ -1401,7 +1401,7 @@ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"জুম নিয়ন্ত্ৰণ কৰিবলৈ দুবাৰ টিপক"</string> <string name="gadget_host_error_inflating" msgid="2449961590495198720">"ৱিজেট যোগ কৰিব পৰা নগ\'ল।"</string> <string name="ime_action_go" msgid="5536744546326495436">"যাওক"</string> - <string name="ime_action_search" msgid="4501435960587287668">"অনুসন্ধান কৰক"</string> + <string name="ime_action_search" msgid="4501435960587287668">"Search"</string> <string name="ime_action_send" msgid="8456843745664334138">"পঠিয়াওক"</string> <string name="ime_action_next" msgid="4169702997635728543">"পৰৱৰ্তী"</string> <string name="ime_action_done" msgid="6299921014822891569">"সম্পন্ন হ’ল"</string> @@ -1881,7 +1881,7 @@ <string name="language_picker_section_suggested" msgid="6556199184638990447">"প্ৰস্তাৱিত"</string> <string name="language_picker_section_all" msgid="1985809075777564284">"সকলো ভাষা"</string> <string name="region_picker_section_all" msgid="756441309928774155">"সকলো অঞ্চল"</string> - <string name="locale_search_menu" msgid="6258090710176422934">"অনুসন্ধান কৰক"</string> + <string name="locale_search_menu" msgid="6258090710176422934">"Search"</string> <string name="app_suspended_title" msgid="888873445010322650">"এপটো নাই"</string> <string name="app_suspended_default_message" msgid="6451215678552004172">"এই মুহূৰ্তত <xliff:g id="APP_NAME_0">%1$s</xliff:g> উপলব্ধ নহয়। ইয়াক <xliff:g id="APP_NAME_1">%2$s</xliff:g>এ পৰিচালনা কৰে।"</string> <string name="app_suspended_more_details" msgid="211260942831587014">"অধিক জানক"</string> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index ffc9ecf02b18..22589cd00b06 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -983,9 +983,9 @@ <string name="menu_space_shortcut_label" msgid="5949311515646872071">"স্পেস"</string> <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"enter"</string> <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"মুছুন"</string> - <string name="search_go" msgid="2141477624421347086">"খুঁজুন"</string> + <string name="search_go" msgid="2141477624421347086">"সার্চ"</string> <string name="search_hint" msgid="455364685740251925">"সার্চ করুন..."</string> - <string name="searchview_description_search" msgid="1045552007537359343">"খুঁজুন"</string> + <string name="searchview_description_search" msgid="1045552007537359343">"সার্চ"</string> <string name="searchview_description_query" msgid="7430242366971716338">"সার্চ ক্যোয়ারী"</string> <string name="searchview_description_clear" msgid="1989371719192982900">"ক্যোয়ারী সাফ করুন"</string> <string name="searchview_description_submit" msgid="6771060386117334686">"ক্যোয়ারী জমা দিন"</string> @@ -1401,7 +1401,7 @@ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"জুম নিয়ন্ত্রণের জন্য দুবার ট্যাপ করুন"</string> <string name="gadget_host_error_inflating" msgid="2449961590495198720">"উইজেট যোগ করা যায়নি৷"</string> <string name="ime_action_go" msgid="5536744546326495436">"যান"</string> - <string name="ime_action_search" msgid="4501435960587287668">"খুঁজুন"</string> + <string name="ime_action_search" msgid="4501435960587287668">"সার্চ"</string> <string name="ime_action_send" msgid="8456843745664334138">"পাঠান"</string> <string name="ime_action_next" msgid="4169702997635728543">"পরবর্তী"</string> <string name="ime_action_done" msgid="6299921014822891569">"সম্পন্ন হয়েছে"</string> @@ -1881,7 +1881,7 @@ <string name="language_picker_section_suggested" msgid="6556199184638990447">"প্রস্তাবিত"</string> <string name="language_picker_section_all" msgid="1985809075777564284">"সকল ভাষা"</string> <string name="region_picker_section_all" msgid="756441309928774155">"সমস্ত অঞ্চল"</string> - <string name="locale_search_menu" msgid="6258090710176422934">"খুঁজুন"</string> + <string name="locale_search_menu" msgid="6258090710176422934">"সার্চ"</string> <string name="app_suspended_title" msgid="888873445010322650">"অ্যাপটি উপলভ্য নয়"</string> <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> এখন উপলভ্য নয়। এই অ্যাপটিকে <xliff:g id="APP_NAME_1">%2$s</xliff:g> অ্যাপ ম্যানেজ করে।"</string> <string name="app_suspended_more_details" msgid="211260942831587014">"আরও জানুন"</string> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index ca35a681f636..5ffc420b13b4 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -985,7 +985,7 @@ <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"ડિલીટ કરો"</string> <string name="search_go" msgid="2141477624421347086">"શોધો"</string> <string name="search_hint" msgid="455364685740251925">"શોધો…"</string> - <string name="searchview_description_search" msgid="1045552007537359343">"શોધ"</string> + <string name="searchview_description_search" msgid="1045552007537359343">"શોધો"</string> <string name="searchview_description_query" msgid="7430242366971716338">"શોધ ક્વેરી"</string> <string name="searchview_description_clear" msgid="1989371719192982900">"ક્વેરી સાફ કરો"</string> <string name="searchview_description_submit" msgid="6771060386117334686">"ક્વેરી સબમિટ કરો"</string> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index cbb9ca2606f2..c7786aebe9e4 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -983,9 +983,9 @@ <string name="menu_space_shortcut_label" msgid="5949311515646872071">"space"</string> <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"enter"</string> <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"ಅಳಿಸಿ"</string> - <string name="search_go" msgid="2141477624421347086">"ಹುಡುಕಿ"</string> + <string name="search_go" msgid="2141477624421347086">"Search"</string> <string name="search_hint" msgid="455364685740251925">"ಹುಡುಕಿ…"</string> - <string name="searchview_description_search" msgid="1045552007537359343">"ಹುಡುಕಿ"</string> + <string name="searchview_description_search" msgid="1045552007537359343">"Search"</string> <string name="searchview_description_query" msgid="7430242366971716338">"ಪ್ರಶ್ನೆಯನ್ನು ಹುಡುಕಿ"</string> <string name="searchview_description_clear" msgid="1989371719192982900">"ಪ್ರಶ್ನೆಯನ್ನು ತೆರವುಗೊಳಿಸು"</string> <string name="searchview_description_submit" msgid="6771060386117334686">"ಪ್ರಶ್ನೆಯನ್ನು ಸಲ್ಲಿಸು"</string> @@ -1401,7 +1401,7 @@ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"ಝೂಮ್ ನಿಯಂತ್ರಿಸಲು ಎರಡು ಬಾರಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="gadget_host_error_inflating" msgid="2449961590495198720">"ವಿಜೆಟ್ ಸೇರಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ."</string> <string name="ime_action_go" msgid="5536744546326495436">"ಹೋಗು"</string> - <string name="ime_action_search" msgid="4501435960587287668">"ಹುಡುಕಿ"</string> + <string name="ime_action_search" msgid="4501435960587287668">"Search"</string> <string name="ime_action_send" msgid="8456843745664334138">"ಕಳುಹಿಸು"</string> <string name="ime_action_next" msgid="4169702997635728543">"ಮುಂದೆ"</string> <string name="ime_action_done" msgid="6299921014822891569">"ಮುಗಿದಿದೆ"</string> @@ -1881,7 +1881,7 @@ <string name="language_picker_section_suggested" msgid="6556199184638990447">"ಸೂಚಿತ ಭಾಷೆ"</string> <string name="language_picker_section_all" msgid="1985809075777564284">"ಎಲ್ಲಾ ಭಾಷೆಗಳು"</string> <string name="region_picker_section_all" msgid="756441309928774155">"ಎಲ್ಲಾ ಪ್ರದೇಶಗಳು"</string> - <string name="locale_search_menu" msgid="6258090710176422934">"ಹುಡುಕಿ"</string> + <string name="locale_search_menu" msgid="6258090710176422934">"Search"</string> <string name="app_suspended_title" msgid="888873445010322650">"ಅಪ್ಲಿಕೇಶನ್ ಲಭ್ಯವಿಲ್ಲ"</string> <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ಅಪ್ಲಿಕೇಶನ್ ಸದ್ಯಕ್ಕೆ ಲಭ್ಯವಿಲ್ಲ. ಇದನ್ನು <xliff:g id="APP_NAME_1">%2$s</xliff:g> ನಲ್ಲಿ ನಿರ್ವಹಿಸಲಾಗುತ್ತಿದೆ."</string> <string name="app_suspended_more_details" msgid="211260942831587014">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index af75969910d2..12c0cb4025ee 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -983,9 +983,9 @@ <string name="menu_space_shortcut_label" msgid="5949311515646872071">"space"</string> <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"enter"</string> <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"delete"</string> - <string name="search_go" msgid="2141477624421347086">"തിരയൽ"</string> + <string name="search_go" msgid="2141477624421347086">"Search"</string> <string name="search_hint" msgid="455364685740251925">"തിരയുക…"</string> - <string name="searchview_description_search" msgid="1045552007537359343">"തിരയൽ"</string> + <string name="searchview_description_search" msgid="1045552007537359343">"Search"</string> <string name="searchview_description_query" msgid="7430242366971716338">"തിരയൽ അന്വേഷണം"</string> <string name="searchview_description_clear" msgid="1989371719192982900">"അന്വേഷണം മായ്ക്കുക"</string> <string name="searchview_description_submit" msgid="6771060386117334686">"ചോദ്യം സമർപ്പിക്കുക"</string> @@ -1401,7 +1401,7 @@ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"സൂം നിയന്ത്രണം ലഭിക്കാൻ രണ്ടുതവണ ടാപ്പുചെയ്യുക"</string> <string name="gadget_host_error_inflating" msgid="2449961590495198720">"വിജറ്റ് ചേർക്കാനായില്ല."</string> <string name="ime_action_go" msgid="5536744546326495436">"പോവുക"</string> - <string name="ime_action_search" msgid="4501435960587287668">"തിരയൽ"</string> + <string name="ime_action_search" msgid="4501435960587287668">"Search"</string> <string name="ime_action_send" msgid="8456843745664334138">"അയയ്ക്കുക"</string> <string name="ime_action_next" msgid="4169702997635728543">"അടുത്തത്"</string> <string name="ime_action_done" msgid="6299921014822891569">"പൂർത്തിയായി"</string> @@ -1881,7 +1881,7 @@ <string name="language_picker_section_suggested" msgid="6556199184638990447">"നിര്ദ്ദേശിച്ചത്"</string> <string name="language_picker_section_all" msgid="1985809075777564284">"എല്ലാ ഭാഷകളും"</string> <string name="region_picker_section_all" msgid="756441309928774155">"എല്ലാ പ്രദേശങ്ങളും"</string> - <string name="locale_search_menu" msgid="6258090710176422934">"തിരയുക"</string> + <string name="locale_search_menu" msgid="6258090710176422934">"Search"</string> <string name="app_suspended_title" msgid="888873445010322650">"ആപ്പ് ലഭ്യമല്ല"</string> <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ഇപ്പോൾ ലഭ്യമല്ല. <xliff:g id="APP_NAME_1">%2$s</xliff:g> ആണ് ഇത് മാനേജ് ചെയ്യുന്നത്."</string> <string name="app_suspended_more_details" msgid="211260942831587014">"കൂടുതലറിയുക"</string> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index ec240c1c36fc..da6f2b71c65a 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -983,9 +983,9 @@ <string name="menu_space_shortcut_label" msgid="5949311515646872071">"स्पेस"</string> <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"एंटर"</string> <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"हटवा"</string> - <string name="search_go" msgid="2141477624421347086">"शोध"</string> + <string name="search_go" msgid="2141477624421347086">"Search"</string> <string name="search_hint" msgid="455364685740251925">"शोधा…"</string> - <string name="searchview_description_search" msgid="1045552007537359343">"शोध"</string> + <string name="searchview_description_search" msgid="1045552007537359343">"Search"</string> <string name="searchview_description_query" msgid="7430242366971716338">"शोध क्वेरी"</string> <string name="searchview_description_clear" msgid="1989371719192982900">"क्वेरी साफ करा"</string> <string name="searchview_description_submit" msgid="6771060386117334686">"क्वेरी सबमिट करा"</string> @@ -1401,7 +1401,7 @@ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"झूम नियंत्रणासाठी दोनदा टॅप करा"</string> <string name="gadget_host_error_inflating" msgid="2449961590495198720">"विजेट जोडू शकलो नाही."</string> <string name="ime_action_go" msgid="5536744546326495436">"जा"</string> - <string name="ime_action_search" msgid="4501435960587287668">"शोधा"</string> + <string name="ime_action_search" msgid="4501435960587287668">"Search"</string> <string name="ime_action_send" msgid="8456843745664334138">"पाठवा"</string> <string name="ime_action_next" msgid="4169702997635728543">"पुढे"</string> <string name="ime_action_done" msgid="6299921014822891569">"पूर्ण झाले"</string> @@ -1881,7 +1881,7 @@ <string name="language_picker_section_suggested" msgid="6556199184638990447">"सुचवलेल्या भाषा"</string> <string name="language_picker_section_all" msgid="1985809075777564284">"सर्व भाषा"</string> <string name="region_picker_section_all" msgid="756441309928774155">"सर्व प्रदेश"</string> - <string name="locale_search_menu" msgid="6258090710176422934">"शोध"</string> + <string name="locale_search_menu" msgid="6258090710176422934">"Search"</string> <string name="app_suspended_title" msgid="888873445010322650">"अॅप उपलब्ध नाही"</string> <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> आत्ता उपलब्ध नाही. हे <xliff:g id="APP_NAME_1">%2$s</xliff:g> कडून व्यवस्थापित केले जाते."</string> <string name="app_suspended_more_details" msgid="211260942831587014">"अधिक जाणून घ्या"</string> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index a1fd3f022555..1cb01ead277b 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -983,9 +983,9 @@ <string name="menu_space_shortcut_label" msgid="5949311515646872071">"ସ୍ପେସ୍"</string> <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"ଏଣ୍ଟର୍"</string> <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"ଡିଲିଟ୍"</string> - <string name="search_go" msgid="2141477624421347086">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string> + <string name="search_go" msgid="2141477624421347086">"Search"</string> <string name="search_hint" msgid="455364685740251925">"ସର୍ଚ୍ଚ…"</string> - <string name="searchview_description_search" msgid="1045552007537359343">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string> + <string name="searchview_description_search" msgid="1045552007537359343">"Search"</string> <string name="searchview_description_query" msgid="7430242366971716338">"କ୍ୱେରୀ ସର୍ଚ୍ଚ କରନ୍ତୁ"</string> <string name="searchview_description_clear" msgid="1989371719192982900">"କ୍ୱେରୀ ଖାଲି କରନ୍ତୁ"</string> <string name="searchview_description_submit" msgid="6771060386117334686">"କ୍ୱେରୀ ଦାଖଲ କରନ୍ତୁ"</string> @@ -1401,7 +1401,7 @@ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"ଜୁମ୍ ନିୟନ୍ତ୍ରଣ ପାଇଁ ଦୁଇଥର ଟାପ୍ କରନ୍ତୁ"</string> <string name="gadget_host_error_inflating" msgid="2449961590495198720">"ୱିଜେଟ୍ ଯୋଡ଼ିପାରିବ ନାହିଁ।"</string> <string name="ime_action_go" msgid="5536744546326495436">"ଯାଆନ୍ତୁ"</string> - <string name="ime_action_search" msgid="4501435960587287668">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string> + <string name="ime_action_search" msgid="4501435960587287668">"Search"</string> <string name="ime_action_send" msgid="8456843745664334138">"ପଠାନ୍ତୁ"</string> <string name="ime_action_next" msgid="4169702997635728543">"ପରବର୍ତ୍ତୀ"</string> <string name="ime_action_done" msgid="6299921014822891569">"ହୋଇଗଲା"</string> @@ -1881,7 +1881,7 @@ <string name="language_picker_section_suggested" msgid="6556199184638990447">"ପ୍ରସ୍ତାବିତ"</string> <string name="language_picker_section_all" msgid="1985809075777564284">"ସମସ୍ତ ଭାଷା"</string> <string name="region_picker_section_all" msgid="756441309928774155">"ସମସ୍ତ ଅଞ୍ଚଳ"</string> - <string name="locale_search_menu" msgid="6258090710176422934">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string> + <string name="locale_search_menu" msgid="6258090710176422934">"Search"</string> <string name="app_suspended_title" msgid="888873445010322650">"ଆପ୍ ଉପଲବ୍ଧ ନାହିଁ"</string> <string name="app_suspended_default_message" msgid="6451215678552004172">"ବର୍ତ୍ତମାନ <xliff:g id="APP_NAME_0">%1$s</xliff:g> ଉପଲବ୍ଧ ନାହିଁ। ଏହା <xliff:g id="APP_NAME_1">%2$s</xliff:g> ଦ୍ଵାରା ପରିଚାଳିତ ହେଉଛି।"</string> <string name="app_suspended_more_details" msgid="211260942831587014">"ଅଧିକ ଜାଣନ୍ତୁ"</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index 3e7ca92681c5..37a995a5a799 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -754,7 +754,7 @@ <string name="phoneTypeFaxHome" msgid="6678559953115904345">"Faks shtëpie"</string> <string name="phoneTypePager" msgid="576402072263522767">"Biper"</string> <string name="phoneTypeOther" msgid="6918196243648754715">"Tjetër"</string> - <string name="phoneTypeCallback" msgid="3455781500844157767">"Ri-telefono"</string> + <string name="phoneTypeCallback" msgid="3455781500844157767">"Kthim telefonate"</string> <string name="phoneTypeCar" msgid="4604775148963129195">"Numri i telefonit të makinës"</string> <string name="phoneTypeCompanyMain" msgid="4482773154536455441">"Numri kryesor i telefonit të kompanisë"</string> <string name="phoneTypeIsdn" msgid="2496238954533998512">"ISDN"</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index 854427b983a0..6b9caf15a745 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -983,9 +983,9 @@ <string name="menu_space_shortcut_label" msgid="5949311515646872071">"space"</string> <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"enter"</string> <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"delete"</string> - <string name="search_go" msgid="2141477624421347086">"వెతుకు"</string> + <string name="search_go" msgid="2141477624421347086">"సెర్చ్"</string> <string name="search_hint" msgid="455364685740251925">"వెతుకు..."</string> - <string name="searchview_description_search" msgid="1045552007537359343">"శోధించండి"</string> + <string name="searchview_description_search" msgid="1045552007537359343">"సెర్చ్"</string> <string name="searchview_description_query" msgid="7430242366971716338">"ప్రశ్నను శోధించండి"</string> <string name="searchview_description_clear" msgid="1989371719192982900">"ప్రశ్నను క్లియర్ చేయి"</string> <string name="searchview_description_submit" msgid="6771060386117334686">"ప్రశ్నని సమర్పించండి"</string> @@ -1401,7 +1401,7 @@ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"జూమ్ నియంత్రణ కోసం రెండుసార్లు నొక్కండి"</string> <string name="gadget_host_error_inflating" msgid="2449961590495198720">"విడ్జెట్ను జోడించడం సాధ్యపడలేదు."</string> <string name="ime_action_go" msgid="5536744546326495436">"వెళ్లు"</string> - <string name="ime_action_search" msgid="4501435960587287668">"వెతుకు"</string> + <string name="ime_action_search" msgid="4501435960587287668">"సెర్చ్"</string> <string name="ime_action_send" msgid="8456843745664334138">"పంపు"</string> <string name="ime_action_next" msgid="4169702997635728543">"తర్వాత"</string> <string name="ime_action_done" msgid="6299921014822891569">"పూర్తయింది"</string> @@ -1881,7 +1881,7 @@ <string name="language_picker_section_suggested" msgid="6556199184638990447">"సూచించినవి"</string> <string name="language_picker_section_all" msgid="1985809075777564284">"అన్ని భాషలు"</string> <string name="region_picker_section_all" msgid="756441309928774155">"అన్ని ప్రాంతాలు"</string> - <string name="locale_search_menu" msgid="6258090710176422934">"వెతుకు"</string> + <string name="locale_search_menu" msgid="6258090710176422934">"సెర్చ్"</string> <string name="app_suspended_title" msgid="888873445010322650">"యాప్ అందుబాటులో లేదు"</string> <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ప్రస్తుతం అందుబాటులో లేదు. ఇది <xliff:g id="APP_NAME_1">%2$s</xliff:g> ద్వారా నిర్వహించబడుతుంది."</string> <string name="app_suspended_more_details" msgid="211260942831587014">"మరింత తెలుసుకోండి"</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 3cb264da95c3..1899f8fd2077 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -1131,10 +1131,10 @@ <string name="whichViewApplication" msgid="5733194231473132945">"Mở bằng"</string> <string name="whichViewApplicationNamed" msgid="415164730629690105">"Mở bằng %1$s"</string> <string name="whichViewApplicationLabel" msgid="7367556735684742409">"Mở"</string> - <string name="whichOpenHostLinksWith" msgid="7645631470199397485">"Mở đường dẫn liên kết <xliff:g id="HOST">%1$s</xliff:g> bằng"</string> - <string name="whichOpenLinksWith" msgid="1120936181362907258">"Mở đường dẫn liên kết bằng"</string> - <string name="whichOpenLinksWithApp" msgid="6917864367861910086">"Mở đường dẫn liên kết bằng <xliff:g id="APPLICATION">%1$s</xliff:g>"</string> - <string name="whichOpenHostLinksWithApp" msgid="2401668560768463004">"Mở đường dẫn liên kết <xliff:g id="HOST">%1$s</xliff:g> bằng <xliff:g id="APPLICATION">%2$s</xliff:g>"</string> + <string name="whichOpenHostLinksWith" msgid="7645631470199397485">"Mở đường liên kết <xliff:g id="HOST">%1$s</xliff:g> bằng"</string> + <string name="whichOpenLinksWith" msgid="1120936181362907258">"Mở đường liên kết bằng"</string> + <string name="whichOpenLinksWithApp" msgid="6917864367861910086">"Mở đường liên kết bằng <xliff:g id="APPLICATION">%1$s</xliff:g>"</string> + <string name="whichOpenHostLinksWithApp" msgid="2401668560768463004">"Mở đường liên kết <xliff:g id="HOST">%1$s</xliff:g> bằng <xliff:g id="APPLICATION">%2$s</xliff:g>"</string> <string name="whichGiveAccessToApplicationLabel" msgid="7805857277166106236">"Cấp quyền truy cập"</string> <string name="whichEditApplication" msgid="6191568491456092812">"Chỉnh sửa bằng"</string> <string name="whichEditApplicationNamed" msgid="8096494987978521514">"Chỉnh sửa bằng %1$s"</string> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index f99be880cbe3..613111d512be 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4189,6 +4189,8 @@ <string-array name="config_biometric_sensors" translatable="false" > <!-- <item>0:2:15</item> ID0:Fingerprint:Strong --> </string-array> + <!--If true, allows the device to load udfps components on older HIDL implementations --> + <bool name="allow_test_udfps" translatable="false" >false</bool> <!-- Messages that should not be shown to the user during face auth enrollment. This should be used to hide messages that may be too chatty or messages that the user can't do much about. diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 040fad5e6410..781e7cff4470 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2506,6 +2506,7 @@ <java-symbol type="string" name="face_error_security_update_required" /> <java-symbol type="array" name="config_biometric_sensors" /> + <java-symbol type="bool" name="allow_test_udfps" /> <java-symbol type="array" name="config_face_acquire_enroll_ignorelist" /> <java-symbol type="array" name="config_face_acquire_vendor_enroll_ignorelist" /> diff --git a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java index 01515bd9c6b5..a80f5a03ee4e 100644 --- a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java @@ -52,7 +52,9 @@ import android.os.SystemClock; import android.provider.Settings; import android.support.test.uiautomator.UiDevice; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.DebugUtils; +import android.util.KeyValueListParser; import android.util.Log; import androidx.test.InstrumentationRegistry; @@ -104,8 +106,6 @@ public class BstatsCpuTimesValidationTest { private static final int WORK_DURATION_MS = 2000; - private static final String DESIRED_PROC_STATE_CPU_TIMES_DELAY = "0"; - private static boolean sBatteryStatsConstsUpdated; private static String sOriginalBatteryStatsConsts; @@ -124,10 +124,12 @@ public class BstatsCpuTimesValidationTest { sContext.getPackageManager().setApplicationEnabledSetting(TEST_PKG, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0); sTestPkgUid = sContext.getPackageManager().getPackageUid(TEST_PKG, 0); + + final ArrayMap<String, String> desiredConstants = new ArrayMap<>(); + desiredConstants.put(KEY_TRACK_CPU_TIMES_BY_PROC_STATE, Boolean.toString(true)); + desiredConstants.put(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS, Integer.toString(0)); + updateBatteryStatsConstants(desiredConstants); checkCpuTimesAvailability(); - if (sPerProcStateTimesAvailable && sCpuFreqTimesAvailable) { - setDesiredReadyDelay(); - } } @AfterClass @@ -139,26 +141,33 @@ public class BstatsCpuTimesValidationTest { batteryReset(); } - private static void setDesiredReadyDelay() { + private static void updateBatteryStatsConstants(ArrayMap<String, String> desiredConstants) { sOriginalBatteryStatsConsts = Settings.Global.getString(sContext.getContentResolver(), Settings.Global.BATTERY_STATS_CONSTANTS); - String newBatteryStatsConstants; - final String newConstant = KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS - + "=" + DESIRED_PROC_STATE_CPU_TIMES_DELAY; - if (sOriginalBatteryStatsConsts == null || "null".equals(sOriginalBatteryStatsConsts)) { - // battery_stats_constants is initially empty, so just assign the desired value. - newBatteryStatsConstants = newConstant; - } else if (sOriginalBatteryStatsConsts.contains(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS)) { - // battery_stats_constants contains delay duration, so replace it - // with the desired value. - newBatteryStatsConstants = sOriginalBatteryStatsConsts.replaceAll( - KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS + "=\\d+", newConstant); - } else { - // battery_stats_constants didn't contain any delay, so append the desired value. - newBatteryStatsConstants = sOriginalBatteryStatsConsts + "," + newConstant; + final char delimiter = ','; + final KeyValueListParser parser = new KeyValueListParser(delimiter); + parser.setString(sOriginalBatteryStatsConsts); + final StringBuilder sb = new StringBuilder(); + for (int i = 0, size = parser.size(); i < size; ++i) { + final String key = parser.keyAt(i); + final String value = desiredConstants.getOrDefault(key, + parser.getString(key, null)); + if (sb.length() > 0) { + sb.append(delimiter); + } + sb.append(key + "=" + value); + desiredConstants.remove(key); } + desiredConstants.forEach((key, value) -> { + if (sb.length() > 0) { + sb.append(delimiter); + } + sb.append(key + '=' + value); + }); Settings.Global.putString(sContext.getContentResolver(), - Settings.Global.BATTERY_STATS_CONSTANTS, newBatteryStatsConstants); + Settings.Global.BATTERY_STATS_CONSTANTS, sb.toString()); + Log.d(TAG, "Updated value of '" + Settings.Global.BATTERY_STATS_CONSTANTS + "': " + + sb.toString()); sBatteryStatsConstsUpdated = true; } diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp index 04007c91817d..d0e688d3efc1 100644 --- a/data/etc/car/Android.bp +++ b/data/etc/car/Android.bp @@ -17,126 +17,126 @@ // Privapp permission whitelist files prebuilt_etc { - name: "privapp_whitelist_android.car.cluster.loggingrenderer", + name: "allowed_privapp_android.car.cluster.loggingrenderer", sub_dir: "permissions", src: "android.car.cluster.loggingrenderer.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_android.car.cluster.sample", + name: "allowed_privapp_android.car.cluster.sample", sub_dir: "permissions", src: "android.car.cluster.sample.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_android.car.cluster", + name: "allowed_privapp_android.car.cluster", sub_dir: "permissions", src: "android.car.cluster.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_android.car.usb.handler", + name: "allowed_privapp_android.car.usb.handler", sub_dir: "permissions", src: "android.car.usb.handler.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.carlauncher", + name: "allowed_privapp_com.android.car.carlauncher", sub_dir: "permissions", src: "com.android.car.carlauncher.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.dialer", + name: "allowed_privapp_com.android.car.dialer", sub_dir: "permissions", src: "com.android.car.dialer.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.hvac", + name: "allowed_privapp_com.android.car.hvac", sub_dir: "permissions", src: "com.android.car.hvac.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.media", + name: "allowed_privapp_com.android.car.media", sub_dir: "permissions", src: "com.android.car.media.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.notification", + name: "allowed_privapp_com.android.car.notification", sub_dir: "permissions", src: "com.android.car.notification.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.radio", + name: "allowed_privapp_com.android.car.radio", sub_dir: "permissions", src: "com.android.car.radio.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.secondaryhome", + name: "allowed_privapp_com.android.car.secondaryhome", sub_dir: "permissions", src: "com.android.car.secondaryhome.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.settings", + name: "allowed_privapp_com.android.car.settings", sub_dir: "permissions", src: "com.android.car.settings.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.themeplayground", + name: "allowed_privapp_com.android.car.themeplayground", sub_dir: "permissions", src: "com.android.car.themeplayground.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car", + name: "allowed_privapp_com.android.car", sub_dir: "permissions", src: "com.android.car.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.bugreport", + name: "allowed_privapp_com.android.car.bugreport", sub_dir: "permissions", src: "com.android.car.bugreport.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.companiondevicesupport", + name: "allowed_privapp_com.android.car.companiondevicesupport", sub_dir: "permissions", src: "com.android.car.companiondevicesupport.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.google.android.car.kitchensink", + name: "allowed_privapp_com.google.android.car.kitchensink", sub_dir: "permissions", src: "com.google.android.car.kitchensink.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.developeroptions", + name: "allowed_privapp_com.android.car.developeroptions", sub_dir: "permissions", src: "com.android.car.developeroptions.xml", filename_from_src: true, @@ -144,14 +144,14 @@ prebuilt_etc { } prebuilt_etc { - name: "privapp_whitelist_com.android.car.floatingcardslauncher", + name: "allowed_privapp_com.android.car.floatingcardslauncher", sub_dir: "permissions", src: "com.android.car.floatingcardslauncher.xml", filename_from_src: true, } prebuilt_etc { - name: "privapp_whitelist_com.android.car.ui.paintbooth", + name: "allowed_privapp_com.android.car.ui.paintbooth", sub_dir: "permissions", src: "com.android.car.ui.paintbooth.xml", filename_from_src: true, diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml index ada8b000a26b..06f1dae30cd3 100644 --- a/data/etc/com.android.systemui.xml +++ b/data/etc/com.android.systemui.xml @@ -35,6 +35,7 @@ <permission name="android.permission.MANAGE_USERS"/> <permission name="android.permission.MASTER_CLEAR"/> <permission name="android.permission.MEDIA_CONTENT_CONTROL"/> + <permission name="android.permission.MODIFY_AUDIO_ROUTING" /> <permission name="android.permission.MODIFY_DAY_NIGHT_MODE"/> <permission name="android.permission.MODIFY_PHONE_STATE"/> <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java index ba3ebddd4b86..4ec752a6dd9e 100644 --- a/drm/java/android/drm/DrmManagerClient.java +++ b/drm/java/android/drm/DrmManagerClient.java @@ -751,7 +751,7 @@ public class DrmManagerClient implements AutoCloseable { /** * Removes all the rights information of every DRM plug-in (agent) associated with - * the DRM framework. Will be used during a master reset. + * the DRM framework. * * @return ERROR_NONE for success; ERROR_UNKNOWN for failure. */ diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index 8bf688dba10b..e148d0e29b5a 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -362,6 +362,11 @@ public class Tuner implements AutoCloseable { */ @Override public void close() { + releaseAll(); + TunerUtils.throwExceptionForResult(nativeClose(), "failed to close tuner"); + } + + private void releaseAll() { if (mFrontendHandle != null) { int res = nativeCloseFrontend(mFrontendHandle); if (res != Tuner.RESULT_SUCCESS) { @@ -396,9 +401,9 @@ public class Tuner implements AutoCloseable { TunerUtils.throwExceptionForResult(res, "failed to close demux"); } mTunerResourceManager.releaseDemux(mDemuxHandle, mClientId); - mFrontendHandle = null; + mDemuxHandle = null; } - TunerUtils.throwExceptionForResult(nativeClose(), "failed to close tuner"); + } /** @@ -495,6 +500,7 @@ public class Tuner implements AutoCloseable { break; } case MSG_RESOURCE_LOST: { + releaseAll(); if (mOnResourceLostListener != null && mOnResourceLostListenerExecutor != null) { mOnResourceLostListenerExecutor.execute( diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java index 39c7682a2a74..1386cba5f9ca 100644 --- a/media/java/android/service/media/MediaBrowserService.java +++ b/media/java/android/service/media/MediaBrowserService.java @@ -684,8 +684,15 @@ public abstract class MediaBrowserService extends Service { List<MediaBrowser.MediaItem> filteredList = (flag & RESULT_FLAG_OPTION_NOT_HANDLED) != 0 ? applyOptions(list, options) : list; - final ParceledListSlice<MediaBrowser.MediaItem> pls = - filteredList == null ? null : new ParceledListSlice<>(filteredList); + final ParceledListSlice<MediaBrowser.MediaItem> pls; + if (filteredList == null) { + pls = null; + } else { + pls = new ParceledListSlice<>(filteredList); + // Limit the size of initial Parcel to prevent binder buffer overflow + // as onLoadChildren is an async binder call. + pls.setInlineCountLimit(1); + } try { connection.callbacks.onLoadChildren(parentId, pls, options); } catch (RemoteException ex) { diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt index f9d0d14c7335..e90fbd4dead8 100644 --- a/non-updatable-api/current.txt +++ b/non-updatable-api/current.txt @@ -45137,7 +45137,7 @@ package android.telephony { method public long getNci(); method @IntRange(from=0, to=3279165) public int getNrarfcn(); method @IntRange(from=0, to=1007) public int getPci(); - method @IntRange(from=0, to=65535) public int getTac(); + method @IntRange(from=0, to=16777215) public int getTac(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellIdentityNr> CREATOR; } diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt index 35b483b9fb84..617a83f05791 100644 --- a/non-updatable-api/module-lib-current.txt +++ b/non-updatable-api/module-lib-current.txt @@ -7,6 +7,7 @@ package android.app { public class NotificationManager { method public boolean hasEnabledNotificationListener(@NonNull String, @NonNull android.os.UserHandle); + field public static final String ACTION_NOTIFICATION_LISTENER_ENABLED_CHANGED = "android.app.action.NOTIFICATION_LISTENER_ENABLED_CHANGED"; } } diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp index 8598f74e1441..08dd79973fa9 100644 --- a/packages/CarSystemUI/Android.bp +++ b/packages/CarSystemUI/Android.bp @@ -128,6 +128,8 @@ android_app { "CarSystemUI-core", ], + export_package_resources: true, + libs: [ "android.car", ], diff --git a/packages/CarSystemUI/proguard.flags b/packages/CarSystemUI/proguard.flags index 516e70f56158..f0b20c105b84 100644 --- a/packages/CarSystemUI/proguard.flags +++ b/packages/CarSystemUI/proguard.flags @@ -1,6 +1,7 @@ -keep class com.android.systemui.CarSystemUIFactory -keep class com.android.car.notification.headsup.animationhelper.** --keep class com.android.systemui.CarGlobalRootComponent { *; } +-keep class com.android.systemui.DaggerCarGlobalRootComponent { *; } +-keep class com.android.systemui.DaggerCarGlobalRootComponent$CarSysUIComponentImpl { *; } -include ../SystemUI/proguard.flags diff --git a/packages/CarSystemUI/res/layout/car_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_navigation_bar.xml index 93174983b116..a49a6373a252 100644 --- a/packages/CarSystemUI/res/layout/car_navigation_bar.xml +++ b/packages/CarSystemUI/res/layout/car_navigation_bar.xml @@ -25,7 +25,7 @@ <!--The 20dp padding is the difference between the background selected icon size and the ripple that was chosen, thus it's a hack to make it look pretty and not an official margin value--> <LinearLayout - android:id="@id/nav_buttons" + android:id="@+id/nav_buttons" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" diff --git a/packages/CarSystemUI/res/values/ids.xml b/packages/CarSystemUI/res/values/ids.xml index 27ed2e250d9f..05194a4d6279 100644 --- a/packages/CarSystemUI/res/values/ids.xml +++ b/packages/CarSystemUI/res/values/ids.xml @@ -18,5 +18,4 @@ <resources> <!-- Values used for finding elements on the system ui nav bars --> <item type="id" name="lock_screen_nav_buttons"/> - <item type="id" name="nav_buttons"/> </resources>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_apps.xml b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_apps.xml new file mode 100644 index 000000000000..a8d8a2f241f6 --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_apps.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:viewportWidth="44" + android:viewportHeight="44" + android:width="44dp" + android:height="44dp"> +<path + android:pathData="M7.33333333 14.6666667L14.6666667 14.6666667L14.6666667 7.33333333L7.33333333 7.33333333L7.33333333 14.6666667ZM18.3333333 36.6666667L25.6666667 36.6666667L25.6666667 29.3333333L18.3333333 29.3333333L18.3333333 36.6666667ZM7.33333333 36.6666667L14.6666667 36.6666667L14.6666667 29.3333333L7.33333333 29.3333333L7.33333333 36.6666667ZM7.33333333 25.6666667L14.6666667 25.6666667L14.6666667 18.3333333L7.33333333 18.3333333L7.33333333 25.6666667ZM18.3333333 25.6666667L25.6666667 25.6666667L25.6666667 18.3333333L18.3333333 18.3333333L18.3333333 25.6666667ZM29.3333333 7.33333333L29.3333333 14.6666667L36.6666667 14.6666667L36.6666667 7.33333333L29.3333333 7.33333333ZM18.3333333 14.6666667L25.6666667 14.6666667L25.6666667 7.33333333L18.3333333 7.33333333L18.3333333 14.6666667ZM29.3333333 25.6666667L36.6666667 25.6666667L36.6666667 18.3333333L29.3333333 18.3333333L29.3333333 25.6666667ZM29.3333333 36.6666667L36.6666667 36.6666667L36.6666667 29.3333333L29.3333333 29.3333333L29.3333333 36.6666667Z" + android:fillColor="@color/car_nav_icon_fill_color" /> +</vector>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_apps_selected.xml b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_apps_selected.xml new file mode 100644 index 000000000000..2a4e91aa3cd9 --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_apps_selected.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:viewportWidth="44" + android:viewportHeight="44" + android:width="44dp" + android:height="44dp"> + <path + android:pathData="M7.33333333 14.6666667L14.6666667 14.6666667L14.6666667 7.33333333L7.33333333 7.33333333L7.33333333 14.6666667ZM18.3333333 36.6666667L25.6666667 36.6666667L25.6666667 29.3333333L18.3333333 29.3333333L18.3333333 36.6666667ZM7.33333333 36.6666667L14.6666667 36.6666667L14.6666667 29.3333333L7.33333333 29.3333333L7.33333333 36.6666667ZM7.33333333 25.6666667L14.6666667 25.6666667L14.6666667 18.3333333L7.33333333 18.3333333L7.33333333 25.6666667ZM18.3333333 25.6666667L25.6666667 25.6666667L25.6666667 18.3333333L18.3333333 18.3333333L18.3333333 25.6666667ZM29.3333333 7.33333333L29.3333333 14.6666667L36.6666667 14.6666667L36.6666667 7.33333333L29.3333333 7.33333333ZM18.3333333 14.6666667L25.6666667 14.6666667L25.6666667 7.33333333L18.3333333 7.33333333L18.3333333 14.6666667ZM29.3333333 25.6666667L36.6666667 25.6666667L36.6666667 18.3333333L29.3333333 18.3333333L29.3333333 25.6666667ZM29.3333333 36.6666667L36.6666667 36.6666667L36.6666667 29.3333333L29.3333333 29.3333333L29.3333333 36.6666667Z" + android:fillColor="@color/car_nav_icon_fill_color_selected" /> +</vector>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_music.xml b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_music.xml new file mode 100644 index 000000000000..6339ebb3ea8d --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_music.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:viewportWidth="44" + android:viewportHeight="44" + android:width="44dp" + android:height="44dp"> + <path + android:pathData="M22 5.5L22 24.8416667C20.9183333 24.2183333 19.6716667 23.8333333 18.3333333 23.8333333C14.2816667 23.8333333 11 27.115 11 31.1666667C11 35.2183333 14.2816667 38.5 18.3333333 38.5C22.385 38.5 25.6666667 35.2183333 25.6666667 31.1666667L25.6666667 12.8333333L33 12.8333333L33 5.5L22 5.5Z" + android:fillColor="@color/car_nav_icon_fill_color" /> +</vector>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_music_selected.xml b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_music_selected.xml new file mode 100644 index 000000000000..a56bcb38d883 --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_music_selected.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:viewportWidth="44" + android:viewportHeight="44" + android:width="44dp" + android:height="44dp"> + <path + android:pathData="M22 5.5L22 24.8416667C20.9183333 24.2183333 19.6716667 23.8333333 18.3333333 23.8333333C14.2816667 23.8333333 11 27.115 11 31.1666667C11 35.2183333 14.2816667 38.5 18.3333333 38.5C22.385 38.5 25.6666667 35.2183333 25.6666667 31.1666667L25.6666667 12.8333333L33 12.8333333L33 5.5L22 5.5Z" + android:fillColor="@color/car_nav_icon_fill_color_selected" /> +</vector>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_navigation.xml b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_navigation.xml new file mode 100644 index 000000000000..e1fabe07cdeb --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_navigation.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:viewportWidth="44" + android:viewportHeight="44" + android:width="44dp" + android:height="44dp"> + <path + android:pathData="M39.8016667 20.6983333L23.3016667 4.19833333C22.5866667 3.48333333 21.4316667 3.48333333 20.7166667 4.19833333L4.21666667 20.6983333C3.50166667 21.4133333 3.50166667 22.5683333 4.21666667 23.2833333L20.7166667 39.7833333C21.4316667 40.4983333 22.5866667 40.4983333 23.3016667 39.7833333L39.8016667 23.2833333C40.5166667 22.5866667 40.5166667 21.4316667 39.8016667 20.6983333ZM25.6666667 26.5833333L25.6666667 22L18.3333333 22L18.3333333 27.5L14.6666667 27.5L14.6666667 20.1666667C14.6666667 19.1583333 15.4916667 18.3333333 16.5 18.3333333L25.6666667 18.3333333L25.6666667 13.75L32.0833333 20.1666667L25.6666667 26.5833333Z" + android:fillColor="@color/car_nav_icon_fill_color" /> +</vector>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_navigation_selected.xml b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_navigation_selected.xml new file mode 100644 index 000000000000..d11cf28f6ca7 --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_navigation_selected.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:viewportWidth="44" + android:viewportHeight="44" + android:width="44dp" + android:height="44dp"> + <path + android:pathData="M39.8016667 20.6983333L23.3016667 4.19833333C22.5866667 3.48333333 21.4316667 3.48333333 20.7166667 4.19833333L4.21666667 20.6983333C3.50166667 21.4133333 3.50166667 22.5683333 4.21666667 23.2833333L20.7166667 39.7833333C21.4316667 40.4983333 22.5866667 40.4983333 23.3016667 39.7833333L39.8016667 23.2833333C40.5166667 22.5866667 40.5166667 21.4316667 39.8016667 20.6983333ZM25.6666667 26.5833333L25.6666667 22L18.3333333 22L18.3333333 27.5L14.6666667 27.5L14.6666667 20.1666667C14.6666667 19.1583333 15.4916667 18.3333333 16.5 18.3333333L25.6666667 18.3333333L25.6666667 13.75L32.0833333 20.1666667L25.6666667 26.5833333Z" + android:fillColor="@color/car_nav_icon_fill_color_selected" /> +</vector>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_overview.xml b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_overview.xml new file mode 100644 index 000000000000..f185eb9afb75 --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_overview.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:viewportWidth="44" + android:viewportHeight="44" + android:width="44dp" + android:height="44dp"> + <path + android:pathData="M36.92857 22.39286A14.53571 14.53571 0 0 1 7.857143 22.39286A14.53571 14.53571 0 0 1 36.92857 22.39286Z" + android:strokeColor="@color/car_nav_icon_fill_color" + android:strokeWidth="4" /> +</vector>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_overview_selected.xml b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_overview_selected.xml new file mode 100644 index 000000000000..19b558363720 --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_overview_selected.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:viewportWidth="44" + android:viewportHeight="44" + android:width="44dp" + android:height="44dp"> + <path + android:pathData="M36.92857 22.39286A14.53571 14.53571 0 0 1 7.857143 22.39286A14.53571 14.53571 0 0 1 36.92857 22.39286Z" + android:strokeColor="@color/car_nav_icon_fill_color_selected" + android:strokeWidth="4" /> +</vector>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_phone.xml b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_phone.xml new file mode 100644 index 000000000000..50e36b5a6e3c --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_phone.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:viewportWidth="44" + android:viewportHeight="44" + android:width="44dp" + android:height="44dp"> + <path + android:pathData="M12.1366667 19.7816667C14.7766667 24.97 19.03 29.205 24.2183333 31.8633333L28.2516667 27.83C28.7466667 27.335 29.48 27.17 30.1216667 27.39C32.175 28.0683333 34.3933333 28.435 36.6666667 28.435C37.675 28.435 38.5 29.26 38.5 30.2683333L38.5 36.6666667C38.5 37.675 37.675 38.5 36.6666667 38.5C19.4516667 38.5 5.5 24.5483333 5.5 7.33333333C5.5 6.325 6.325 5.5 7.33333333 5.5L13.75 5.5C14.7583333 5.5 15.5833333 6.325 15.5833333 7.33333333C15.5833333 9.625 15.95 11.825 16.6283333 13.8783333C16.83 14.52 16.6833333 15.235 16.17 15.7483333L12.1366667 19.7816667Z" + android:fillColor="@color/car_nav_icon_fill_color" /> +</vector>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_phone_selected.xml b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_phone_selected.xml new file mode 100644 index 000000000000..11b1687cf1c1 --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/drawable/car_ic_phone_selected.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:viewportWidth="44" + android:viewportHeight="44" + android:width="44dp" + android:height="44dp"> + <path + android:pathData="M12.1366667 19.7816667C14.7766667 24.97 19.03 29.205 24.2183333 31.8633333L28.2516667 27.83C28.7466667 27.335 29.48 27.17 30.1216667 27.39C32.175 28.0683333 34.3933333 28.435 36.6666667 28.435C37.675 28.435 38.5 29.26 38.5 30.2683333L38.5 36.6666667C38.5 37.675 37.675 38.5 36.6666667 38.5C19.4516667 38.5 5.5 24.5483333 5.5 7.33333333C5.5 6.325 6.325 5.5 7.33333333 5.5L13.75 5.5C14.7583333 5.5 15.5833333 6.325 15.5833333 7.33333333C15.5833333 9.625 15.95 11.825 16.6283333 13.8783333C16.83 14.52 16.6833333 15.235 16.17 15.7483333L12.1366667 19.7816667Z" + android:fillColor="@color/car_nav_icon_fill_color_selected" /> +</vector>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/drawable/system_bar_background.xml b/packages/CarSystemUI/samples/sample1/rro/res/drawable/system_bar_background.xml new file mode 100644 index 000000000000..6161ad9b041c --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/drawable/system_bar_background.xml @@ -0,0 +1,33 @@ +<?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" > + <corners + android:topLeftRadius="0dp" + android:topRightRadius="10dp" + android:bottomLeftRadius="0dp" + android:bottomRightRadius="0dp" + /> + <solid + android:color="#404040" + /> + <padding + android:left="0dp" + android:top="0dp" + android:right="0dp" + android:bottom="0dp" + /> +</shape>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/drawable/system_bar_background_2.xml b/packages/CarSystemUI/samples/sample1/rro/res/drawable/system_bar_background_2.xml new file mode 100644 index 000000000000..35821426bee3 --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/drawable/system_bar_background_2.xml @@ -0,0 +1,33 @@ +<?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" > + <corners + android:topLeftRadius="10dp" + android:topRightRadius="0dp" + android:bottomLeftRadius="0dp" + android:bottomRightRadius="0dp" + /> + <solid + android:color="#404040" + /> + <padding + android:left="0dp" + android:top="0dp" + android:right="0dp" + android:bottom="0dp" + /> +</shape>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/drawable/system_bar_background_3.xml b/packages/CarSystemUI/samples/sample1/rro/res/drawable/system_bar_background_3.xml new file mode 100644 index 000000000000..afa5b32136a8 --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/drawable/system_bar_background_3.xml @@ -0,0 +1,33 @@ +<?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" > + <corners + android:topLeftRadius="0dp" + android:topRightRadius="0dp" + android:bottomLeftRadius="10dp" + android:bottomRightRadius="0dp" + /> + <solid + android:color="#404040" + /> + <padding + android:left="0dp" + android:top="0dp" + android:right="0dp" + android:bottom="0dp" + /> +</shape>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/layout/car_navigation_bar.xml b/packages/CarSystemUI/samples/sample1/rro/res/layout/car_navigation_bar.xml new file mode 100644 index 000000000000..4358d977bcc3 --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/layout/car_navigation_bar.xml @@ -0,0 +1,88 @@ +<?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. + --> +<com.android.systemui.car.navigationbar.CarNavigationBarView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:systemui="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@android:color/transparent" + android:orientation="horizontal"> + <!--The 20dp padding is the difference between the background selected icon size and the ripple + that was chosen, thus it's a hack to make it look pretty and not an official margin value--> + <LinearLayout + android:id="@+id/nav_buttons" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@drawable/system_bar_background" + android:gravity="center" + android:layoutDirection="ltr" + android:paddingEnd="20dp" + android:paddingStart="20dp"> + + <com.android.systemui.car.navigationbar.CarNavigationButton + android:id="@+id/home" + style="@style/NavigationBarButton" + systemui:componentNames="com.android.car.carlauncher/.CarLauncher" + systemui:icon="@drawable/car_ic_overview" + systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end" + systemui:selectedIcon="@drawable/car_ic_overview_selected" + systemui:highlightWhenSelected="true" + /> + + <com.android.systemui.car.navigationbar.CarNavigationButton + android:id="@+id/maps_nav" + style="@style/NavigationBarButton" + systemui:categories="android.intent.category.APP_MAPS" + systemui:icon="@drawable/car_ic_navigation" + systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MAPS;launchFlags=0x14000000;end" + systemui:selectedIcon="@drawable/car_ic_navigation_selected" + systemui:highlightWhenSelected="true" + /> + + <com.android.systemui.car.navigationbar.CarNavigationButton + android:id="@+id/music_nav" + style="@style/NavigationBarButton" + systemui:categories="android.intent.category.APP_MUSIC" + systemui:icon="@drawable/car_ic_music" + systemui:intent="intent:#Intent;action=android.car.intent.action.MEDIA_TEMPLATE;launchFlags=0x10000000;end" + systemui:packages="com.android.car.media" + systemui:selectedIcon="@drawable/car_ic_music_selected" + systemui:highlightWhenSelected="true" + /> + + <com.android.systemui.car.navigationbar.CarNavigationButton + android:id="@+id/phone_nav" + style="@style/NavigationBarButton" + systemui:icon="@drawable/car_ic_phone" + systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;package=com.android.car.dialer;launchFlags=0x10000000;end" + systemui:packages="com.android.car.dialer" + systemui:selectedIcon="@drawable/car_ic_phone_selected" + systemui:highlightWhenSelected="true" + /> + + <com.android.systemui.car.navigationbar.CarNavigationButton + android:id="@+id/grid_nav" + style="@style/NavigationBarButton" + systemui:componentNames="com.android.car.carlauncher/.AppGridActivity" + systemui:icon="@drawable/car_ic_apps" + systemui:intent="intent:#Intent;component=com.android.car.carlauncher/.AppGridActivity;launchFlags=0x24000000;end" + systemui:selectedIcon="@drawable/car_ic_apps_selected" + systemui:highlightWhenSelected="true" + /> + + </LinearLayout> +</com.android.systemui.car.navigationbar.CarNavigationBarView> diff --git a/packages/CarSystemUI/samples/sample1/rro/res/layout/car_right_navigation_bar.xml b/packages/CarSystemUI/samples/sample1/rro/res/layout/car_right_navigation_bar.xml new file mode 100644 index 000000000000..dc1d0d64a40b --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/layout/car_right_navigation_bar.xml @@ -0,0 +1,141 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +** +** Copyright 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. +*/ +--> + +<com.android.systemui.car.navigationbar.CarNavigationBarView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:systemui="http://schemas.android.com/apk/res-auto" + android:layout_height="match_parent" + android:layout_width="match_parent" + android:orientation="vertical" + android:baselineAligned="false" + android:background="@android:color/transparent"> + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="110dp" + android:background="@drawable/system_bar_background_3"> + <FrameLayout + android:id="@+id/clock_container" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_centerInParent="true"> + <com.android.systemui.car.navigationbar.CarNavigationButton + android:id="@+id/qs" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@null" + systemui:intent="intent:#Intent;component=com.android.car.settings/.common.CarSettingActivities$QuickSettingActivity;launchFlags=0x24000000;end" + /> + <com.android.systemui.statusbar.policy.Clock + android:id="@+id/clock" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:elevation="5dp" + android:singleLine="true" + android:textAppearance="@style/TextAppearance.StatusBar.Clock" + /> + </FrameLayout> + </RelativeLayout> + <View + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="110dp" + android:layout_gravity="bottom" + android:orientation="horizontal" + android:background="@drawable/system_bar_background_2"> + + <FrameLayout + android:id="@+id/left_hvac_container" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_alignParentStart="true"> + + <com.android.systemui.car.navigationbar.CarNavigationButton + android:id="@+id/hvacleft" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@null" + systemui:broadcast="true" + systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end" + /> + + <com.android.systemui.car.hvac.AnimatedTemperatureView + android:id="@+id/lefttext" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:paddingStart="@*android:dimen/car_padding_4" + android:paddingEnd="16dp" + android:gravity="center_vertical|start" + android:minEms="4" + android:textAppearance="@style/TextAppearance.CarStatus" + systemui:hvacAreaId="49" + systemui:hvacMaxText="Max" + systemui:hvacMaxValue="126" + systemui:hvacMinText="Min" + systemui:hvacMinValue="0" + systemui:hvacPivotOffset="60dp" + systemui:hvacPropertyId="358614275" + systemui:hvacTempFormat="%.0f\u00B0" + /> + </FrameLayout> + <View + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + /> + <FrameLayout + android:id="@+id/right_hvac_container" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_alignParentEnd="true"> + + <com.android.systemui.car.navigationbar.CarNavigationButton + android:id="@+id/hvacright" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@null" + systemui:broadcast="true" + systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end" + /> + + <com.android.systemui.car.hvac.AnimatedTemperatureView + android:id="@+id/righttext" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:paddingStart="16dp" + android:paddingEnd="@*android:dimen/car_padding_4" + android:gravity="center_vertical|end" + android:minEms="4" + android:textAppearance="@style/TextAppearance.CarStatus" + systemui:hvacAreaId="68" + systemui:hvacMaxText="Max" + systemui:hvacMaxValue="126" + systemui:hvacMinText="Min" + systemui:hvacMinValue="0" + systemui:hvacPivotOffset="60dp" + systemui:hvacPropertyId="358614275" + systemui:hvacTempFormat="%.0f\u00B0" + /> + </FrameLayout> + </LinearLayout> +</com.android.systemui.car.navigationbar.CarNavigationBarView> diff --git a/packages/CarSystemUI/samples/sample1/rro/res/layout/system_icons.xml b/packages/CarSystemUI/samples/sample1/rro/res/layout/system_icons.xml new file mode 100644 index 000000000000..d23579294ce8 --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/layout/system_icons.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/system_icons" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center_vertical"> + + <com.android.systemui.statusbar.phone.StatusIconContainer + android:id="@+id/statusIcons" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:paddingEnd="4dp" + android:gravity="center_vertical" + android:orientation="horizontal" + /> +</LinearLayout>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/values/attrs.xml b/packages/CarSystemUI/samples/sample1/rro/res/values/attrs.xml new file mode 100644 index 000000000000..e02f9e6e9a72 --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/values/attrs.xml @@ -0,0 +1,44 @@ +<?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> + <attr name="broadcast" format="boolean"/> + <attr name="icon" format="reference"/> + <attr name="selectedIcon" format="reference"/> + <attr name="intent" format="string"/> + <attr name="longIntent" format="string"/> + <attr name="componentNames" format="string" /> + <attr name="highlightWhenSelected" format="boolean" /> + <attr name="categories" format="string"/> + <attr name="packages" format="string" /> + + <!-- Custom attributes to configure hvac values --> + <declare-styleable name="AnimatedTemperatureView"> + <attr name="hvacAreaId" format="integer"/> + <attr name="hvacPropertyId" format="integer"/> + <attr name="hvacTempFormat" format="string"/> + <!-- how far away the animations should center around --> + <attr name="hvacPivotOffset" format="dimension"/> + <attr name="hvacMinValue" format="float"/> + <attr name="hvacMaxValue" format="float"/> + <attr name="hvacMinText" format="string|reference"/> + <attr name="hvacMaxText" format="string|reference"/> + <attr name="android:gravity"/> + <attr name="android:minEms"/> + <attr name="android:textAppearance"/> + </declare-styleable> +</resources> diff --git a/packages/CarSystemUI/samples/sample1/rro/res/values/colors.xml b/packages/CarSystemUI/samples/sample1/rro/res/values/colors.xml new file mode 100644 index 000000000000..c32d638681a2 --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/values/colors.xml @@ -0,0 +1,20 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android"> + <color name="car_nav_icon_fill_color">#8F8F8F</color> + <color name="car_nav_icon_fill_color_selected">#FFFFFF</color> +</resources> diff --git a/packages/CarSystemUI/samples/sample1/rro/res/values/config.xml b/packages/CarSystemUI/samples/sample1/rro/res/values/config.xml index 854ab7d7e49b..2ec90e95d707 100644 --- a/packages/CarSystemUI/samples/sample1/rro/res/values/config.xml +++ b/packages/CarSystemUI/samples/sample1/rro/res/values/config.xml @@ -17,8 +17,8 @@ <resources> <!-- Configure which system bars should be displayed. --> - <bool name="config_enableTopNavigationBar">true</bool> - <bool name="config_enableLeftNavigationBar">true</bool> + <bool name="config_enableTopNavigationBar">false</bool> + <bool name="config_enableLeftNavigationBar">false</bool> <bool name="config_enableRightNavigationBar">true</bool> <bool name="config_enableBottomNavigationBar">true</bool> @@ -28,8 +28,8 @@ <!-- 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_leftSystemBarType">0</integer> + <integer name="config_rightSystemBarType">0</integer> <integer name="config_bottomSystemBarType">1</integer> <!-- Configure the relative z-order among the system bars. When two system bars overlap (e.g. @@ -40,8 +40,19 @@ 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_topSystemBarZOrder">0</integer> <integer name="config_leftSystemBarZOrder">0</integer> - <integer name="config_rightSystemBarZOrder">0</integer> + <integer name="config_rightSystemBarZOrder">11</integer> <integer name="config_bottomSystemBarZOrder">10</integer> + + <!-- Whether heads-up notifications should be shown on the bottom. If false, heads-up + notifications will be shown pushed to the top of their parent container. If true, they will + be shown pushed to the bottom of their parent container. If true, then should override + config_headsUpNotificationAnimationHelper to use a different AnimationHelper, such as + com.android.car.notification.headsup.animationhelper. + CarHeadsUpNotificationBottomAnimationHelper. --> + <bool name="config_showHeadsUpNotificationOnBottom">true</bool> + + <string name="config_notificationPanelViewMediator" translatable="false"> + com.android.systemui.car.notification.BottomNotificationPanelViewMediator</string> </resources>
\ No newline at end of file diff --git a/packages/CarSystemUI/samples/sample1/rro/res/values/dimens.xml b/packages/CarSystemUI/samples/sample1/rro/res/values/dimens.xml new file mode 100644 index 000000000000..cdfed27c64a7 --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/values/dimens.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<resources> + <dimen name="car_right_navigation_bar_width">280dp</dimen> +</resources> diff --git a/packages/CarSystemUI/samples/sample1/rro/res/values/styles.xml b/packages/CarSystemUI/samples/sample1/rro/res/values/styles.xml new file mode 100644 index 000000000000..136dc3b6df18 --- /dev/null +++ b/packages/CarSystemUI/samples/sample1/rro/res/values/styles.xml @@ -0,0 +1,35 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android"> + <style name="TextAppearance.StatusBar.Clock" + parent="@*android:style/TextAppearance.StatusBar.Icon"> + <item name="android:textSize">40sp</item> + <item name="android:fontFamily">sans-serif-regular</item> + <item name="android:textColor">#FFFFFF</item> + </style> + + <style name="NavigationBarButton"> + <item name="android:layout_height">96dp</item> + <item name="android:layout_width">96dp</item> + <item name="android:background">?android:attr/selectableItemBackground</item> + </style> + + <style name="TextAppearance.CarStatus" parent="@android:style/TextAppearance.DeviceDefault"> + <item name="android:textSize">30sp</item> + <item name="android:textColor">#FFFFFF</item> + </style> +</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 index 7bcb8e1b43dd..b8e1edc46da7 100644 --- a/packages/CarSystemUI/samples/sample1/rro/res/xml/car_sysui_overlays.xml +++ b/packages/CarSystemUI/samples/sample1/rro/res/xml/car_sysui_overlays.xml @@ -16,10 +16,50 @@ --> <overlay> + <item target="layout/car_navigation_bar" value="@layout/car_navigation_bar"/> + <item target="layout/system_icons" value="@layout/system_icons"/> + <item target="layout/car_right_navigation_bar" value="@layout/car_right_navigation_bar"/> + + <item target="attr/icon" value="@attr/icon"/> + <item target="attr/selectedIcon" value="@attr/selectedIcon"/> + <item target="attr/intent" value="@attr/longIntent"/> + <item target="attr/componentNames" value="@attr/componentNames"/> + <item target="attr/highlightWhenSelected" value="@attr/highlightWhenSelected"/> + <item target="attr/categories" value="@attr/categories"/> + <item target="attr/packages" value="@attr/packages"/> + <item target="attr/hvacAreaId" value="@attr/hvacAreaId"/> + <item target="attr/hvacPropertyId" value="@attr/hvacPropertyId"/> + <item target="attr/hvacTempFormat" value="@attr/hvacTempFormat"/> + <item target="attr/hvacPivotOffset" value="@attr/hvacPivotOffset"/> + <item target="attr/hvacMinValue" value="@attr/hvacMinValue"/> + <item target="attr/hvacMaxValue" value="@attr/hvacMaxValue"/> + <item target="attr/hvacMinText" value="@attr/hvacMinText"/> + <item target="attr/hvacMaxText" value="@attr/hvacMaxText"/> + <!-- start the intent as a broad cast instead of an activity if true--> + <item target="attr/broadcast" value="@attr/broadcast"/> + + <item target="drawable/car_ic_overview" value="@drawable/car_ic_overview" /> + <item target="drawable/car_ic_overview_selected" value="@drawable/car_ic_overview_selected" /> + <item target="drawable/car_ic_apps" value="@drawable/car_ic_apps" /> + <item target="drawable/car_ic_apps_selected" value="@drawable/car_ic_apps_selected" /> + <item target="drawable/car_ic_music" value="@drawable/car_ic_music" /> + <item target="drawable/car_ic_music_selected" value="@drawable/car_ic_music_selected" /> + <item target="drawable/car_ic_phone" value="@drawable/car_ic_phone" /> + <item target="drawable/car_ic_phone_selected" value="@drawable/car_ic_phone_selected" /> + <item target="drawable/car_ic_navigation" value="@drawable/car_ic_navigation" /> + <item target="drawable/car_ic_navigation_selected" value="@drawable/car_ic_navigation_selected" /> + + <item target="dimen/car_right_navigation_bar_width" value="@dimen/car_right_navigation_bar_width" /> + + <item target="style/NavigationBarButton" value="@style/NavigationBarButton"/> + + <item target="color/car_nav_icon_fill_color" value="@color/car_nav_icon_fill_color" /> + <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="bool/config_showHeadsUpNotificationOnBottom" value="@bool/config_showHeadsUpNotificationOnBottom"/> <item target="integer/config_topSystemBarType" value="@integer/config_topSystemBarType"/> <item target="integer/config_leftSystemBarType" value="@integer/config_leftSystemBarType"/> @@ -30,4 +70,6 @@ <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"/> + + <item target="string/config_notificationPanelViewMediator" value="@string/config_notificationPanelViewMediator"/> </overlay>
\ No newline at end of file diff --git a/packages/CarSystemUI/src/com/android/systemui/CarGlobalRootComponent.java b/packages/CarSystemUI/src/com/android/systemui/CarGlobalRootComponent.java index fde0b1a97e46..552cadfe967e 100644 --- a/packages/CarSystemUI/src/com/android/systemui/CarGlobalRootComponent.java +++ b/packages/CarSystemUI/src/com/android/systemui/CarGlobalRootComponent.java @@ -16,13 +16,7 @@ package com.android.systemui; -import com.android.systemui.dagger.DependencyBinder; -import com.android.systemui.dagger.DependencyProvider; import com.android.systemui.dagger.GlobalRootComponent; -import com.android.systemui.dagger.SystemServicesModule; -import com.android.systemui.dagger.SystemUIModule; -import com.android.systemui.onehanded.dagger.OneHandedModule; -import com.android.systemui.pip.phone.dagger.PipModule; import javax.inject.Singleton; @@ -32,15 +26,7 @@ import dagger.Component; @Singleton @Component( modules = { - CarComponentBinder.class, - DependencyProvider.class, - DependencyBinder.class, - PipModule.class, - OneHandedModule.class, - SystemServicesModule.class, - SystemUIModule.class, - CarSystemUIModule.class, - CarSystemUIBinder.class + CarSysUIComponentModule.class }) public interface CarGlobalRootComponent extends GlobalRootComponent { /** diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java b/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java index d19f368f22b6..b2f98ecde513 100644 --- a/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java +++ b/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java @@ -16,8 +16,14 @@ package com.android.systemui; +import com.android.systemui.dagger.DependencyBinder; +import com.android.systemui.dagger.DependencyProvider; import com.android.systemui.dagger.SysUIComponent; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.SystemServicesModule; +import com.android.systemui.dagger.SystemUIModule; +import com.android.systemui.onehanded.dagger.OneHandedModule; +import com.android.systemui.pip.phone.dagger.PipModule; import dagger.Subcomponent; @@ -25,7 +31,16 @@ import dagger.Subcomponent; * Dagger Subcomponent for Core SysUI. */ @SysUISingleton -@Subcomponent(modules = {}) +@Subcomponent(modules = { + CarComponentBinder.class, + DependencyProvider.class, + DependencyBinder.class, + PipModule.class, + OneHandedModule.class, + SystemServicesModule.class, + SystemUIModule.class, + CarSystemUIModule.class, + CarSystemUIBinder.class}) public interface CarSysUIComponent extends SysUIComponent { /** diff --git a/tests/AutoVerify/app1/src/com/android/test/autoverify/MainActivity.java b/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponentModule.java index 09ef47212622..4de316693c10 100644 --- a/tests/AutoVerify/app1/src/com/android/test/autoverify/MainActivity.java +++ b/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponentModule.java @@ -13,3 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +package com.android.systemui; + +import dagger.Module; + +/** + * Dagger module for including the CarSysUIComponent. + * + * TODO(b/162923491): Remove or otherwise refactor this module. This is a stop gap. + */ +@Module(subcomponents = {CarSysUIComponent.class}) +public abstract class CarSysUIComponentModule { +} diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java index 53dd947a7eff..290700fad147 100644 --- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java +++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java @@ -22,24 +22,23 @@ import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME; import android.content.Context; import android.os.Handler; import android.os.PowerManager; -import android.view.IWindowManager; import com.android.keyguard.KeyguardViewController; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.car.CarDeviceProvisionedController; import com.android.systemui.car.CarDeviceProvisionedControllerImpl; import com.android.systemui.car.keyguard.CarKeyguardViewController; +import com.android.systemui.car.notification.NotificationShadeWindowControllerImpl; import com.android.systemui.car.statusbar.DozeServiceHost; -import com.android.systemui.car.statusbar.DummyNotificationShadeWindowController; import com.android.systemui.car.volume.CarVolumeDialogComponent; import com.android.systemui.dagger.GlobalRootComponent; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dock.DockManager; import com.android.systemui.dock.DockManagerImpl; import com.android.systemui.doze.DozeHost; -import com.android.systemui.pip.phone.PipMenuActivity; -import com.android.systemui.pip.phone.dagger.PipMenuActivityClass; import com.android.systemui.plugins.qs.QSFactory; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.power.EnhancedEstimates; @@ -52,12 +51,12 @@ import com.android.systemui.stackdivider.DividerModule; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl; import com.android.systemui.statusbar.phone.NotificationGroupManager; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.ShadeControllerImpl; import com.android.systemui.statusbar.policy.BatteryController; @@ -66,14 +65,9 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.volume.VolumeDialogComponent; -import com.android.systemui.wm.DisplaySystemBarsController; -import com.android.wm.shell.common.DisplayController; -import com.android.wm.shell.common.DisplayImeController; -import com.android.wm.shell.common.SystemWindows; -import com.android.wm.shell.common.TransactionPool; +import com.android.systemui.wmshell.CarWMShellModule; import javax.inject.Named; -import javax.inject.Singleton; import dagger.Binds; import dagger.Module; @@ -82,21 +76,19 @@ import dagger.Provides; @Module( includes = { DividerModule.class, - QSModule.class - }, - subcomponents = { - CarSysUIComponent.class + QSModule.class, + CarWMShellModule.class }) abstract class CarSystemUIModule { - @Singleton + @SysUISingleton @Provides @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) static boolean provideAllowNotificationLongPress() { return false; } - @Singleton + @SysUISingleton @Provides static HeadsUpManagerPhone provideHeadsUpManagerPhone( Context context, @@ -108,7 +100,7 @@ abstract class CarSystemUIModule { groupManager, configurationController); } - @Singleton + @SysUISingleton @Provides @Named(LEAK_REPORT_EMAIL_NAME) static String provideLeakReportEmail() { @@ -116,48 +108,12 @@ abstract class CarSystemUIModule { } @Provides - @Singleton + @SysUISingleton static Recents provideRecents(Context context, RecentsImplementation recentsImplementation, CommandQueue commandQueue) { return new Recents(context, recentsImplementation, commandQueue); } - @Singleton - @Provides - static TransactionPool provideTransactionPool() { - return new TransactionPool(); - } - - @Singleton - @Provides - static DisplayController providerDisplayController(Context context, @Main Handler handler, - IWindowManager wmService) { - return new DisplayController(context, handler, wmService); - } - - @Singleton - @Provides - static SystemWindows provideSystemWindows(DisplayController displayController, - IWindowManager wmService) { - return new SystemWindows(displayController, wmService); - } - - @Singleton - @Provides - static DisplayImeController provideDisplayImeController(Context context, - IWindowManager wmService, DisplayController displayController, - @Main Handler mainHandler, TransactionPool transactionPool) { - return new DisplaySystemBarsController.Builder(context, wmService, displayController, - mainHandler, transactionPool).build(); - } - - @Singleton - @PipMenuActivityClass - @Provides - static Class<?> providePipMenuActivityClass() { - return PipMenuActivity.class; - } - @Binds abstract HeadsUpManager bindHeadsUpManagerPhone(HeadsUpManagerPhone headsUpManagerPhone); @@ -169,19 +125,20 @@ abstract class CarSystemUIModule { NotificationLockscreenUserManagerImpl notificationLockscreenUserManager); @Provides - @Singleton + @SysUISingleton static BatteryController provideBatteryController(Context context, EnhancedEstimates enhancedEstimates, PowerManager powerManager, - BroadcastDispatcher broadcastDispatcher, @Main Handler mainHandler, + BroadcastDispatcher broadcastDispatcher, DemoModeController demoModeController, + @Main Handler mainHandler, @Background Handler bgHandler) { BatteryController bC = new BatteryControllerImpl(context, enhancedEstimates, powerManager, - broadcastDispatcher, mainHandler, bgHandler); + broadcastDispatcher, demoModeController, mainHandler, bgHandler); bC.init(); return bC; } @Binds - @Singleton + @SysUISingleton public abstract QSFactory bindQSFactory(QSFactoryImpl qsFactoryImpl); @Binds @@ -207,6 +164,10 @@ abstract class CarSystemUIModule { CarKeyguardViewController carKeyguardViewController); @Binds + abstract NotificationShadeWindowController bindNotificationShadeController( + NotificationShadeWindowControllerImpl notificationPanelViewController); + + @Binds abstract DeviceProvisionedController bindDeviceProvisionedController( CarDeviceProvisionedControllerImpl deviceProvisionedController); @@ -215,9 +176,5 @@ abstract class CarSystemUIModule { CarDeviceProvisionedControllerImpl deviceProvisionedController); @Binds - abstract NotificationShadeWindowController bindNotificationShadeWindowController( - DummyNotificationShadeWindowController notificationShadeWindowController); - - @Binds abstract DozeHost bindDozeHost(DozeServiceHost dozeServiceHost); } diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java b/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java index 09e62d240a72..a2ba880facfe 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java @@ -27,17 +27,17 @@ import android.provider.Settings; import com.android.systemui.Dependency; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl; import javax.inject.Inject; -import javax.inject.Singleton; /** * A controller that monitors the status of SUW progress for each user in addition to the * functionality provided by {@link DeviceProvisionedControllerImpl}. */ -@Singleton +@SysUISingleton public class CarDeviceProvisionedControllerImpl extends DeviceProvisionedControllerImpl implements CarDeviceProvisionedController { private static final Uri USER_SETUP_IN_PROGRESS_URI = Settings.Secure.getUriFor( diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarServiceProvider.java b/packages/CarSystemUI/src/com/android/systemui/car/CarServiceProvider.java index 80ee37127965..5778d660a672 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/CarServiceProvider.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/CarServiceProvider.java @@ -21,14 +21,15 @@ import android.content.Context; import androidx.annotation.VisibleForTesting; +import com.android.systemui.dagger.SysUISingleton; + import java.util.ArrayList; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** Provides a common connection to the car service that can be shared. */ -@Singleton +@SysUISingleton public class CarServiceProvider { private final Context mContext; diff --git a/packages/CarSystemUI/src/com/android/systemui/car/hvac/HvacController.java b/packages/CarSystemUI/src/com/android/systemui/car/hvac/HvacController.java index 236a6a451ea4..a4b6bfc58d3c 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/hvac/HvacController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/hvac/HvacController.java @@ -29,6 +29,7 @@ import android.view.View; import android.view.ViewGroup; import com.android.systemui.car.CarServiceProvider; +import com.android.systemui.dagger.SysUISingleton; import java.util.ArrayList; import java.util.HashMap; @@ -40,13 +41,12 @@ import java.util.Objects; import java.util.Set; import javax.inject.Inject; -import javax.inject.Singleton; /** * Manages the connection to the Car service and delegates value changes to the registered * {@link TemperatureView}s */ -@Singleton +@SysUISingleton public class HvacController { public static final String TAG = "HvacController"; private static final boolean DEBUG = true; diff --git a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java index 51a7245ea5c6..276ddfbc2b4f 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java @@ -38,6 +38,7 @@ import com.android.systemui.car.CarServiceProvider; import com.android.systemui.car.navigationbar.CarNavigationBarController; import com.android.systemui.car.window.OverlayViewController; import com.android.systemui.car.window.OverlayViewGlobalStateController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.plugins.FalsingManager; @@ -49,7 +50,6 @@ import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.KeyguardStateController; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; @@ -57,7 +57,7 @@ import dagger.Lazy; * Automotive implementation of the {@link KeyguardViewController}. It controls the Keyguard View * that is mounted to the SystemUIOverlayWindow. */ -@Singleton +@SysUISingleton public class CarKeyguardViewController extends OverlayViewController implements KeyguardViewController { private static final String TAG = "CarKeyguardViewController"; diff --git a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewMediator.java b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewMediator.java index 5a35c482fb36..155b73e691ef 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewMediator.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewMediator.java @@ -18,15 +18,15 @@ package com.android.systemui.car.keyguard; import com.android.systemui.car.userswitcher.FullScreenUserSwitcherViewController; import com.android.systemui.car.window.OverlayViewMediator; +import com.android.systemui.dagger.SysUISingleton; import javax.inject.Inject; -import javax.inject.Singleton; /** * Manages events originating from the Keyguard service that cause Keyguard or other OverlayWindow * Components to appear or disappear. */ -@Singleton +@SysUISingleton public class CarKeyguardViewMediator implements OverlayViewMediator { private final CarKeyguardViewController mCarKeyguardViewController; diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonRoleHolderController.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonRoleHolderController.java index 5c83c025bc20..f8cd20fe8377 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonRoleHolderController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonRoleHolderController.java @@ -30,13 +30,13 @@ import android.view.ViewGroup; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.car.CarDeviceProvisionedController; +import com.android.systemui.dagger.SysUISingleton; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; -import javax.inject.Singleton; /** * Some CarNavigationButtons can be associated to a {@link RoleManager} role. When they are, it is @@ -46,7 +46,7 @@ import javax.inject.Singleton; * This class monitors the current role holders for each role type and updates the button icon for * this buttons with have this feature enabled. */ -@Singleton +@SysUISingleton public class ButtonRoleHolderController { private static final String TAG = "ButtonRoleHolderController"; diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateController.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateController.java index eedcfa548e5a..aa6da89e2864 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateController.java @@ -26,13 +26,14 @@ import android.view.Display; import android.view.View; import android.view.ViewGroup; +import com.android.systemui.dagger.SysUISingleton; + import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.inject.Inject; -import javax.inject.Singleton; /** * CarNavigationButtons can optionally have selection state that toggles certain visual indications @@ -42,7 +43,7 @@ import javax.inject.Singleton; * This class controls the selection state of CarNavigationButtons that have opted in to have such * selection state-dependent visual indications. */ -@Singleton +@SysUISingleton public class ButtonSelectionStateController { private final Set<CarNavigationButton> mRegisteredViews = new HashSet<>(); diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateListener.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateListener.java index 13617983b23b..d6216ba87d95 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateListener.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateListener.java @@ -19,16 +19,16 @@ package com.android.systemui.car.navigationbar; import android.app.ActivityTaskManager; import android.util.Log; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.shared.system.TaskStackChangeListener; import javax.inject.Inject; -import javax.inject.Singleton; /** * An implementation of TaskStackChangeListener, that listens for changes in the system * task stack and notifies the navigation bar. */ -@Singleton +@SysUISingleton class ButtonSelectionStateListener extends TaskStackChangeListener { private static final String TAG = ButtonSelectionStateListener.class.getSimpleName(); diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java index fe26040c5eae..51a883809aab 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java @@ -23,14 +23,14 @@ import android.view.ViewGroup; import androidx.annotation.Nullable; import com.android.systemui.car.hvac.HvacController; +import com.android.systemui.dagger.SysUISingleton; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; /** A single class which controls the navigation bar views. */ -@Singleton +@SysUISingleton public class CarNavigationBarController { private final Context mContext; diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/NavigationBarViewFactory.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/NavigationBarViewFactory.java index adf8d4d5acf8..a473bb7423b7 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/NavigationBarViewFactory.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/NavigationBarViewFactory.java @@ -26,12 +26,12 @@ import androidx.annotation.LayoutRes; import com.android.car.ui.FocusParkingView; import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; import javax.inject.Inject; -import javax.inject.Singleton; /** A factory that creates and caches views for navigation bars. */ -@Singleton +@SysUISingleton public class NavigationBarViewFactory { private static final String TAG = NavigationBarViewFactory.class.getSimpleName(); diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java index 3527bf93682f..143c444fc4be 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java @@ -29,6 +29,7 @@ import android.view.WindowManager; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import java.lang.annotation.ElementType; @@ -40,13 +41,12 @@ import java.util.Map; import java.util.Set; import javax.inject.Inject; -import javax.inject.Singleton; /** * Reads configs for system bars for each side (TOP, BOTTOM, LEFT, and RIGHT) and returns the * corresponding {@link android.view.WindowManager.LayoutParams} per the configuration. */ -@Singleton +@SysUISingleton public class SystemBarConfigs { private static final String TAG = SystemBarConfigs.class.getSimpleName(); diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/BottomNotificationPanelViewMediator.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/BottomNotificationPanelViewMediator.java index 7d353f5acd9a..8468bef1750c 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/notification/BottomNotificationPanelViewMediator.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/BottomNotificationPanelViewMediator.java @@ -20,16 +20,16 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.car.CarDeviceProvisionedController; import com.android.systemui.car.navigationbar.CarNavigationBarController; import com.android.systemui.car.window.OverlayPanelViewController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.policy.ConfigurationController; import javax.inject.Inject; -import javax.inject.Singleton; /** * Implementation of NotificationPanelViewMediator that sets the notification panel to be opened * from the top navigation bar. */ -@Singleton +@SysUISingleton public class BottomNotificationPanelViewMediator extends NotificationPanelViewMediator { @Inject diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/CarHeadsUpNotificationSystemContainer.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/CarHeadsUpNotificationSystemContainer.java index d4f720715a69..3b22a30857a9 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/notification/CarHeadsUpNotificationSystemContainer.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/CarHeadsUpNotificationSystemContainer.java @@ -29,15 +29,15 @@ import com.android.car.notification.R; import com.android.car.notification.headsup.CarHeadsUpNotificationContainer; import com.android.systemui.car.CarDeviceProvisionedController; import com.android.systemui.car.window.OverlayViewGlobalStateController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import javax.inject.Inject; -import javax.inject.Singleton; /** * A controller for SysUI's HUN display. */ -@Singleton +@SysUISingleton public class CarHeadsUpNotificationSystemContainer implements CarHeadsUpNotificationContainer { private final CarDeviceProvisionedController mCarDeviceProvisionedController; private final OverlayViewGlobalStateController mOverlayViewGlobalStateController; diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/CarNotificationModule.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/CarNotificationModule.java index b7bc63150ea9..8a3bcfc5ef3a 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/notification/CarNotificationModule.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/CarNotificationModule.java @@ -25,8 +25,7 @@ import com.android.car.notification.NotificationClickHandlerFactory; import com.android.car.notification.NotificationDataManager; import com.android.car.notification.headsup.CarHeadsUpNotificationContainer; import com.android.internal.statusbar.IStatusBarService; - -import javax.inject.Singleton; +import com.android.systemui.dagger.SysUISingleton; import dagger.Binds; import dagger.Module; @@ -38,26 +37,26 @@ import dagger.Provides; @Module public abstract class CarNotificationModule { @Provides - @Singleton + @SysUISingleton static NotificationClickHandlerFactory provideNotificationClickHandlerFactory( IStatusBarService barService) { return new NotificationClickHandlerFactory(barService); } @Provides - @Singleton + @SysUISingleton static NotificationDataManager provideNotificationDataManager() { return new NotificationDataManager(); } @Provides - @Singleton + @SysUISingleton static CarUxRestrictionManagerWrapper provideCarUxRestrictionManagerWrapper() { return new CarUxRestrictionManagerWrapper(); } @Provides - @Singleton + @SysUISingleton static CarNotificationListener provideCarNotificationListener(Context context, CarUxRestrictionManagerWrapper carUxRestrictionManagerWrapper, CarHeadsUpNotificationManager carHeadsUpNotificationManager, @@ -69,7 +68,7 @@ public abstract class CarNotificationModule { } @Provides - @Singleton + @SysUISingleton static CarHeadsUpNotificationManager provideCarHeadsUpNotificationManager(Context context, NotificationClickHandlerFactory notificationClickHandlerFactory, NotificationDataManager notificationDataManager, diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java index 8d5843635e5f..3b22fdb50765 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java @@ -49,6 +49,7 @@ import com.android.systemui.car.CarDeviceProvisionedController; import com.android.systemui.car.CarServiceProvider; import com.android.systemui.car.window.OverlayPanelViewController; import com.android.systemui.car.window.OverlayViewGlobalStateController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -59,10 +60,9 @@ import com.android.systemui.statusbar.StatusBarState; import java.util.concurrent.Executor; import javax.inject.Inject; -import javax.inject.Singleton; /** View controller for the notification panel. */ -@Singleton +@SysUISingleton public class NotificationPanelViewController extends OverlayPanelViewController implements CommandQueue.Callbacks { diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewMediator.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewMediator.java index 0c185bae8199..17b6b74014e4 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewMediator.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewMediator.java @@ -31,16 +31,16 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.car.CarDeviceProvisionedController; import com.android.systemui.car.navigationbar.CarNavigationBarController; import com.android.systemui.car.window.OverlayViewMediator; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.policy.ConfigurationController; import javax.inject.Inject; -import javax.inject.Singleton; /** * The view mediator which attaches the view controller to other elements of the system ui. Disables * drag open behavior of the notification panel from any navigation bar. */ -@Singleton +@SysUISingleton public class NotificationPanelViewMediator implements OverlayViewMediator, ConfigurationController.ConfigurationListener { diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationShadeWindowControllerImpl.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationShadeWindowControllerImpl.java new file mode 100644 index 000000000000..1a1da89f147a --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationShadeWindowControllerImpl.java @@ -0,0 +1,46 @@ +/* + * 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.car.notification; + +import com.android.systemui.car.window.OverlayViewGlobalStateController; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.statusbar.NotificationShadeWindowController; + +import javax.inject.Inject; + +/** The automotive version of the notification shade window controller. */ +@SysUISingleton +public class NotificationShadeWindowControllerImpl implements + NotificationShadeWindowController { + + private final OverlayViewGlobalStateController mController; + + @Inject + public NotificationShadeWindowControllerImpl(OverlayViewGlobalStateController controller) { + mController = controller; + } + + @Override + public void setForceDozeBrightness(boolean forceDozeBrightness) { + // No-op since dozing is not supported in Automotive devices. + } + + @Override + public void setNotificationShadeFocusable(boolean focusable) { + mController.setWindowFocusable(focusable); + } +} diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationVisibilityLogger.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationVisibilityLogger.java index 44c819711bd2..b263f721d29a 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationVisibilityLogger.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationVisibilityLogger.java @@ -24,19 +24,19 @@ import com.android.car.notification.AlertEntry; import com.android.car.notification.NotificationDataManager; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.UiBackground; import java.util.Set; import java.util.concurrent.Executor; import javax.inject.Inject; -import javax.inject.Singleton; /** * Handles notification logging, in particular, logging which notifications are visible and which * are not. */ -@Singleton +@SysUISingleton public class NotificationVisibilityLogger { private static final String TAG = "NotificationVisibilityLogger"; diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/PowerManagerHelper.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/PowerManagerHelper.java index 92a11d8db88f..da43c5487623 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/notification/PowerManagerHelper.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/PowerManagerHelper.java @@ -23,14 +23,14 @@ import android.car.hardware.power.CarPowerManager.CarPowerStateListener; import android.util.Log; import com.android.systemui.car.CarServiceProvider; +import com.android.systemui.dagger.SysUISingleton; import javax.inject.Inject; -import javax.inject.Singleton; /** * Helper class for connecting to the {@link CarPowerManager} and listening for power state changes. */ -@Singleton +@SysUISingleton public class PowerManagerHelper { public static final String TAG = "PowerManagerHelper"; diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/TopNotificationPanelViewMediator.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/TopNotificationPanelViewMediator.java index 89c9931ac76e..9bc5b74cda6c 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/notification/TopNotificationPanelViewMediator.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/TopNotificationPanelViewMediator.java @@ -20,16 +20,16 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.car.CarDeviceProvisionedController; import com.android.systemui.car.navigationbar.CarNavigationBarController; import com.android.systemui.car.window.OverlayPanelViewController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.policy.ConfigurationController; import javax.inject.Inject; -import javax.inject.Singleton; /** * Implementation of NotificationPanelViewMediator that sets the notification panel to be opened * from the top navigation bar. */ -@Singleton +@SysUISingleton public class TopNotificationPanelViewMediator extends NotificationPanelViewMediator { @Inject diff --git a/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppController.java b/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppController.java index 6b41b35f7625..b8d6964fa32d 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppController.java @@ -22,14 +22,14 @@ import android.os.RemoteException; import android.util.Log; import com.android.systemui.SystemUI; +import com.android.systemui.dagger.SysUISingleton; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controller responsible for detecting unsafe apps. */ -@Singleton +@SysUISingleton public class SideLoadedAppController extends SystemUI { private static final String TAG = SideLoadedAppController.class.getSimpleName(); diff --git a/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppDetector.java b/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppDetector.java index a2cd0446d1e8..eb32edb27196 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppDetector.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppDetector.java @@ -29,19 +29,19 @@ import android.util.Log; import com.android.systemui.R; import com.android.systemui.car.CarDeviceProvisionedController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import java.util.Arrays; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * A class that detects unsafe apps. * An app is considered safe if is a system app or installed through allowed sources. */ -@Singleton +@SysUISingleton public class SideLoadedAppDetector { private static final String TAG = SideLoadedAppDetector.class.getSimpleName(); diff --git a/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppStateController.java b/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppStateController.java index 1d66ddaf7aa9..5b4faa152685 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppStateController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppStateController.java @@ -19,13 +19,14 @@ package com.android.systemui.car.sideloaded; import android.util.Log; import android.view.Display; +import com.android.systemui.dagger.SysUISingleton; + import javax.inject.Inject; -import javax.inject.Singleton; /** * Manager responsible for displaying proper UI when an unsafe app is detected. */ -@Singleton +@SysUISingleton public class SideLoadedAppStateController { private static final String TAG = SideLoadedAppStateController.class.getSimpleName(); diff --git a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/DozeServiceHost.java b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/DozeServiceHost.java index d23660c2445d..3fb3cd8833b9 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/DozeServiceHost.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/DozeServiceHost.java @@ -16,13 +16,13 @@ package com.android.systemui.car.statusbar; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.doze.DozeHost; import javax.inject.Inject; -import javax.inject.Singleton; /** No-op implementation of {@link DozeHost} for use by car sysui, which does not support dozing. */ -@Singleton +@SysUISingleton public class DozeServiceHost implements DozeHost { @Inject diff --git a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/DummyNotificationShadeWindowController.java b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/DummyNotificationShadeWindowController.java deleted file mode 100644 index 13f2b7ed45db..000000000000 --- a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/DummyNotificationShadeWindowController.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.car.statusbar; - -import android.app.IActivityManager; -import android.content.Context; -import android.view.WindowManager; - -import com.android.systemui.car.window.SystemUIOverlayWindowController; -import com.android.systemui.colorextraction.SysuiColorExtractor; -import com.android.systemui.dump.DumpManager; -import com.android.systemui.keyguard.KeyguardViewMediator; -import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.statusbar.phone.BiometricUnlockController; -import com.android.systemui.statusbar.phone.DozeParameters; -import com.android.systemui.statusbar.phone.KeyguardBypassController; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; -import com.android.systemui.statusbar.policy.ConfigurationController; - -import javax.inject.Inject; -import javax.inject.Singleton; - -/** - * A dummy implementation of {@link NotificationShadeWindowController}. - * - * TODO(b/155711562): This should be replaced with a longer term solution (i.e. separating - * {@link BiometricUnlockController} from the views it depends on). - */ -@Singleton -public class DummyNotificationShadeWindowController extends NotificationShadeWindowController { - private final SystemUIOverlayWindowController mOverlayWindowController; - - @Inject - public DummyNotificationShadeWindowController(Context context, - WindowManager windowManager, IActivityManager activityManager, - DozeParameters dozeParameters, - StatusBarStateController statusBarStateController, - ConfigurationController configurationController, - KeyguardViewMediator keyguardViewMediator, - KeyguardBypassController keyguardBypassController, - SysuiColorExtractor colorExtractor, - DumpManager dumpManager, - SystemUIOverlayWindowController overlayWindowController) { - super(context, windowManager, activityManager, dozeParameters, statusBarStateController, - configurationController, keyguardViewMediator, keyguardBypassController, - colorExtractor, dumpManager); - mOverlayWindowController = overlayWindowController; - } - - @Override - public void setForceDozeBrightness(boolean forceDozeBrightness) { - // No op. - } - - @Override - public void setNotificationShadeFocusable(boolean focusable) { - // The overlay window is the car sysui equivalent of the notification shade. - mOverlayWindowController.setWindowFocusable(focusable); - } -} diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullScreenUserSwitcherViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullScreenUserSwitcherViewController.java index 1a8f19e46798..66bfb2d316ae 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullScreenUserSwitcherViewController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullScreenUserSwitcherViewController.java @@ -30,15 +30,15 @@ import com.android.systemui.R; import com.android.systemui.car.CarServiceProvider; import com.android.systemui.car.window.OverlayViewController; import com.android.systemui.car.window.OverlayViewGlobalStateController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controller for {@link R.layout#car_fullscreen_user_switcher}. */ -@Singleton +@SysUISingleton public class FullScreenUserSwitcherViewController extends OverlayViewController { private final Context mContext; private final Resources mResources; diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullscreenUserSwitcherViewMediator.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullscreenUserSwitcherViewMediator.java index 8b399f888eb3..165fe63c7f37 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullscreenUserSwitcherViewMediator.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullscreenUserSwitcherViewMediator.java @@ -18,16 +18,16 @@ package com.android.systemui.car.userswitcher; import com.android.systemui.car.keyguard.CarKeyguardViewController; import com.android.systemui.car.window.OverlayViewMediator; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.StatusBarState; import javax.inject.Inject; -import javax.inject.Singleton; /** * Manages the fullscreen user switcher and it's interactions with the keyguard. */ -@Singleton +@SysUISingleton public class FullscreenUserSwitcherViewMediator implements OverlayViewMediator { private static final String TAG = FullscreenUserSwitcherViewMediator.class.getSimpleName(); diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewController.java index 0d77c1341ffb..6178cbd3a599 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewController.java @@ -38,15 +38,15 @@ import com.android.settingslib.drawable.CircleFramedDrawable; import com.android.systemui.R; import com.android.systemui.car.window.OverlayViewController; import com.android.systemui.car.window.OverlayViewGlobalStateController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import javax.inject.Inject; -import javax.inject.Singleton; /** * Handles showing and hiding UserSwitchTransitionView that is mounted to SystemUiOverlayWindow. */ -@Singleton +@SysUISingleton public class UserSwitchTransitionViewController extends OverlayViewController { private static final String TAG = "UserSwitchTransition"; private static final String ENABLE_DEVELOPER_MESSAGE_TRUE = "true"; diff --git a/packages/CarSystemUI/src/com/android/systemui/car/volume/CarVolumeDialogComponent.java b/packages/CarSystemUI/src/com/android/systemui/car/volume/CarVolumeDialogComponent.java index 98d24b1fc0e4..4cdbfa3236c8 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/volume/CarVolumeDialogComponent.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/volume/CarVolumeDialogComponent.java @@ -19,18 +19,19 @@ package com.android.systemui.car.volume; import android.content.Context; import com.android.systemui.car.CarServiceProvider; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.demomode.DemoModeController; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.plugins.VolumeDialog; import com.android.systemui.volume.VolumeDialogComponent; import com.android.systemui.volume.VolumeDialogControllerImpl; import javax.inject.Inject; -import javax.inject.Singleton; /** * Allows for adding car specific dialog when the volume dialog is created. */ -@Singleton +@SysUISingleton public class CarVolumeDialogComponent extends VolumeDialogComponent { private CarVolumeDialogImpl mCarVolumeDialog; @@ -38,8 +39,9 @@ public class CarVolumeDialogComponent extends VolumeDialogComponent { @Inject public CarVolumeDialogComponent(Context context, KeyguardViewMediator keyguardViewMediator, VolumeDialogControllerImpl volumeDialogController, + DemoModeController demoModeController, CarServiceProvider carServiceProvider) { - super(context, keyguardViewMediator, volumeDialogController); + super(context, keyguardViewMediator, volumeDialogController, demoModeController); mCarVolumeDialog.setCarServiceProvider(carServiceProvider); } diff --git a/packages/CarSystemUI/src/com/android/systemui/car/volume/VolumeUI.java b/packages/CarSystemUI/src/com/android/systemui/car/volume/VolumeUI.java index 03b61e076c73..b0321abfedd4 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/volume/VolumeUI.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/volume/VolumeUI.java @@ -27,6 +27,7 @@ import android.util.Log; import com.android.systemui.R; import com.android.systemui.SystemUI; import com.android.systemui.car.CarServiceProvider; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.volume.VolumeDialogComponent; @@ -34,12 +35,11 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; /** The entry point for controlling the volume ui in cars. */ -@Singleton +@SysUISingleton public class VolumeUI extends SystemUI { private static final String TAG = "VolumeUI"; diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java index 2494242c24f0..22b6455dbe2b 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java @@ -27,6 +27,8 @@ import android.view.WindowInsetsController; import androidx.annotation.VisibleForTesting; +import com.android.systemui.dagger.SysUISingleton; + import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -35,7 +37,6 @@ import java.util.SortedMap; import java.util.TreeMap; import javax.inject.Inject; -import javax.inject.Singleton; /** * This controller is responsible for the following: @@ -46,7 +47,7 @@ import javax.inject.Singleton; * global state of SystemUIOverlayWindow. * </ul> */ -@Singleton +@SysUISingleton public class OverlayViewGlobalStateController { private static final boolean DEBUG = false; private static final String TAG = OverlayViewGlobalStateController.class.getSimpleName(); diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java index 029bd3702afe..81b1bf930e7e 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java @@ -29,17 +29,17 @@ import android.view.WindowInsets; import android.view.WindowManager; import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.policy.ConfigurationController; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controls the expansion state of the primary window which will contain all of the fullscreen sysui * behavior. This window still has a collapsed state in order to watch for swipe events to expand * this window for the notification panel. */ -@Singleton +@SysUISingleton public class SystemUIOverlayWindowController implements ConfigurationController.ConfigurationListener { diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowManager.java b/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowManager.java index 8cca0ed308b2..6395ebff5a41 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowManager.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowManager.java @@ -21,6 +21,7 @@ import android.util.Log; import com.android.systemui.R; import com.android.systemui.SystemUI; +import com.android.systemui.dagger.SysUISingleton; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -28,13 +29,12 @@ import java.util.Map; import javax.inject.Inject; import javax.inject.Provider; -import javax.inject.Singleton; /** * Registers {@link OverlayViewMediator}(s) and synchronizes their calls to hide/show {@link * OverlayViewController}(s) to allow for the correct visibility of system bars. */ -@Singleton +@SysUISingleton public class SystemUIOverlayWindowManager extends SystemUI { private static final String TAG = "SystemUIOverlayWM"; private final Map<Class<?>, Provider<OverlayViewMediator>> diff --git a/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java new file mode 100644 index 000000000000..2324c3d59155 --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java @@ -0,0 +1,54 @@ +/* + * 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.wmshell; + +import android.content.Context; +import android.os.Handler; +import android.view.IWindowManager; + +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.pip.phone.PipMenuActivity; +import com.android.systemui.pip.phone.dagger.PipMenuActivityClass; +import com.android.systemui.wm.DisplaySystemBarsController; +import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.common.DisplayImeController; +import com.android.wm.shell.common.TransactionPool; + +import dagger.Module; +import dagger.Provides; + +/** Provides dependencies from {@link com.android.wm.shell} for CarSystemUI. */ +@Module(includes = WMShellBaseModule.class) +public class CarWMShellModule { + @SysUISingleton + @Provides + DisplayImeController provideDisplayImeController(Context context, + IWindowManager wmService, DisplayController displayController, + @Main Handler mainHandler, TransactionPool transactionPool) { + return new DisplaySystemBarsController.Builder(context, wmService, displayController, + mainHandler, transactionPool).build(); + } + + /** TODO(b/150319024): PipMenuActivity will move to a Window */ + @SysUISingleton + @PipMenuActivityClass + @Provides + Class<?> providePipMenuActivityClass() { + return PipMenuActivity.class; + } +} diff --git a/packages/PrintSpooler/res/values-as/strings.xml b/packages/PrintSpooler/res/values-as/strings.xml index a93fceb87959..b6b287ff66aa 100644 --- a/packages/PrintSpooler/res/values-as/strings.xml +++ b/packages/PrintSpooler/res/values-as/strings.xml @@ -47,7 +47,7 @@ <string name="savetopdf_button" msgid="2976186791686924743">"PDFৰ জৰিয়তে ছেভ কৰক"</string> <string name="print_options_expanded" msgid="6944679157471691859">"প্ৰিণ্ট বিকল্পসমূহ বিস্তাৰ কৰা হ’ল"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"প্ৰিণ্ট বিকল্পসমূহ সংকুচিত কৰা হ’ল"</string> - <string name="search" msgid="5421724265322228497">"সন্ধান কৰক"</string> + <string name="search" msgid="5421724265322228497">"Search"</string> <string name="all_printers_label" msgid="3178848870161526399">"সকলো প্ৰিণ্টাৰ"</string> <string name="add_print_service_label" msgid="5356702546188981940">"সেৱা যোগ কৰক"</string> <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"সন্ধান বাকচটো দেখুওৱা হ’ল"</string> diff --git a/packages/PrintSpooler/res/values-bn/strings.xml b/packages/PrintSpooler/res/values-bn/strings.xml index 637becbe23f0..b2e1eed85f0c 100644 --- a/packages/PrintSpooler/res/values-bn/strings.xml +++ b/packages/PrintSpooler/res/values-bn/strings.xml @@ -47,7 +47,7 @@ <string name="savetopdf_button" msgid="2976186791686924743">"পিডিএফ হিসাবে সেভ করুন"</string> <string name="print_options_expanded" msgid="6944679157471691859">"প্রিন্ট বিকল্প প্রসারিত হয়েছে"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"প্রিন্ট বিকল্প সংকুচিত হয়েছে"</string> - <string name="search" msgid="5421724265322228497">"খুঁজুন"</string> + <string name="search" msgid="5421724265322228497">"সার্চ"</string> <string name="all_printers_label" msgid="3178848870161526399">"সমস্ত প্রিন্টার"</string> <string name="add_print_service_label" msgid="5356702546188981940">"পরিষেবা যোগ করুন"</string> <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"সার্চ বাক্স দেখানো হচ্ছে"</string> diff --git a/packages/PrintSpooler/res/values-kn/strings.xml b/packages/PrintSpooler/res/values-kn/strings.xml index 150ede4f8e62..261fe4b0de9a 100644 --- a/packages/PrintSpooler/res/values-kn/strings.xml +++ b/packages/PrintSpooler/res/values-kn/strings.xml @@ -47,7 +47,7 @@ <string name="savetopdf_button" msgid="2976186791686924743">"PDF ಗೆ ಉಳಿಸು"</string> <string name="print_options_expanded" msgid="6944679157471691859">"ಪ್ರಿಂಟ್ ಆಯ್ಕೆಗಳನ್ನು ವಿಸ್ತರಿಸಲಾಗಿದೆ"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"ಪ್ರಿಂಟ್ ಆಯ್ಕೆಗಳನ್ನು ಮುಚ್ಚಲಾಗಿದೆ"</string> - <string name="search" msgid="5421724265322228497">"ಹುಡುಕಿ"</string> + <string name="search" msgid="5421724265322228497">"Search"</string> <string name="all_printers_label" msgid="3178848870161526399">"ಎಲ್ಲಾ ಪ್ರಿಂಟರ್ಗಳು"</string> <string name="add_print_service_label" msgid="5356702546188981940">"ಸೇವೆಯನ್ನು ಸೇರಿಸು"</string> <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"ಹುಡುಕಾಟ ಪೆಟ್ಟಿಗೆಯನ್ನು ತೋರಿಸಲಾಗಿದೆ"</string> diff --git a/packages/PrintSpooler/res/values-ml/strings.xml b/packages/PrintSpooler/res/values-ml/strings.xml index dbcd34b1360d..73af95d2e117 100644 --- a/packages/PrintSpooler/res/values-ml/strings.xml +++ b/packages/PrintSpooler/res/values-ml/strings.xml @@ -47,7 +47,7 @@ <string name="savetopdf_button" msgid="2976186791686924743">"PDF-ൽ സംരക്ഷിക്കുക"</string> <string name="print_options_expanded" msgid="6944679157471691859">"പ്രിന്റ് ചെയ്യാനുള്ള ഓപ്ഷനുകൾ വിപുലീകരിച്ചു"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"പ്രിന്റ് ചെയ്യാനുള്ള ഓപ്ഷനുകൾ ചുരുക്കി"</string> - <string name="search" msgid="5421724265322228497">"തിരയൽ"</string> + <string name="search" msgid="5421724265322228497">"Search"</string> <string name="all_printers_label" msgid="3178848870161526399">"എല്ലാ പ്രിന്ററുകളും"</string> <string name="add_print_service_label" msgid="5356702546188981940">"സേവനം ചേർക്കുക"</string> <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"തിരയൽ ബോക്സ് ദൃശ്യമാക്കിയിരിക്കുന്നു"</string> diff --git a/packages/PrintSpooler/res/values-mr/strings.xml b/packages/PrintSpooler/res/values-mr/strings.xml index 44456b4cae05..4d7e919ad125 100644 --- a/packages/PrintSpooler/res/values-mr/strings.xml +++ b/packages/PrintSpooler/res/values-mr/strings.xml @@ -47,7 +47,7 @@ <string name="savetopdf_button" msgid="2976186791686924743">"पीडीएफ वर सेव्ह करा"</string> <string name="print_options_expanded" msgid="6944679157471691859">"प्रिंट पर्याय विस्तृत झाले"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"प्रिंट पर्याय संक्षिप्त झाले"</string> - <string name="search" msgid="5421724265322228497">"शोध"</string> + <string name="search" msgid="5421724265322228497">"Search"</string> <string name="all_printers_label" msgid="3178848870161526399">"सर्व प्रिंटर"</string> <string name="add_print_service_label" msgid="5356702546188981940">"सेवा जोडा"</string> <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"शोध बॉक्स दर्शविला"</string> diff --git a/packages/PrintSpooler/res/values-or/strings.xml b/packages/PrintSpooler/res/values-or/strings.xml index a1675fa7ca76..7000b95b35d6 100644 --- a/packages/PrintSpooler/res/values-or/strings.xml +++ b/packages/PrintSpooler/res/values-or/strings.xml @@ -47,7 +47,7 @@ <string name="savetopdf_button" msgid="2976186791686924743">"PDFରେ ସେଭ୍ କରନ୍ତୁ"</string> <string name="print_options_expanded" msgid="6944679157471691859">"ପ୍ରିଣ୍ଟ ବିକଳ୍ପକୁ ବଡ଼ କରାଯାଇଛି"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"ପ୍ରିଣ୍ଟ ବିକଳ୍ପକୁ ଛୋଟ କରାଯାଇଛି"</string> - <string name="search" msgid="5421724265322228497">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string> + <string name="search" msgid="5421724265322228497">"Search"</string> <string name="all_printers_label" msgid="3178848870161526399">"ସମସ୍ତ ପ୍ରିଣ୍ଟର୍"</string> <string name="add_print_service_label" msgid="5356702546188981940">"ସେବା ଯୋଗ କରନ୍ତୁ"</string> <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"ସର୍ଚ୍ଚ ବକ୍ସ ଦେଖାଯାଇଛି"</string> diff --git a/packages/PrintSpooler/res/values-te/strings.xml b/packages/PrintSpooler/res/values-te/strings.xml index b01b50a60f6b..79944bb9994c 100644 --- a/packages/PrintSpooler/res/values-te/strings.xml +++ b/packages/PrintSpooler/res/values-te/strings.xml @@ -47,7 +47,7 @@ <string name="savetopdf_button" msgid="2976186791686924743">"PDF వలె సేవ్ చేయి"</string> <string name="print_options_expanded" msgid="6944679157471691859">"ముద్రణ ఎంపికలు విస్తరించబడ్డాయి"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"ముద్రణ ఎంపికలు కుదించబడ్డాయి"</string> - <string name="search" msgid="5421724265322228497">"వెతుకు"</string> + <string name="search" msgid="5421724265322228497">"సెర్చ్"</string> <string name="all_printers_label" msgid="3178848870161526399">"అన్ని ప్రింటర్లు"</string> <string name="add_print_service_label" msgid="5356702546188981940">"సేవను జోడించు"</string> <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"శోధన పెట్టె చూపబడింది"</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java index b7ae3dca5c16..bc58bfc97718 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java @@ -189,10 +189,12 @@ public class WifiStatusTracker { } } updateStatusLabel(); + mCallback.run(); } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) { // Default to -200 as its below WifiManager.MIN_RSSI. updateRssi(intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200)); updateStatusLabel(); + mCallback.run(); } } @@ -218,13 +220,15 @@ public class WifiStatusTracker { return; } NetworkCapabilities networkCapabilities; - final Network currentWifiNetwork = mWifiManager.getCurrentNetwork(); - if (currentWifiNetwork != null && currentWifiNetwork.equals(mDefaultNetwork)) { + isDefaultNetwork = false; + if (mDefaultNetworkCapabilities != null) { + isDefaultNetwork = mDefaultNetworkCapabilities.hasTransport( + NetworkCapabilities.TRANSPORT_WIFI); + } + if (isDefaultNetwork) { // Wifi is connected and the default network. - isDefaultNetwork = true; networkCapabilities = mDefaultNetworkCapabilities; } else { - isDefaultNetwork = false; networkCapabilities = mConnectivityManager.getNetworkCapabilities( mWifiManager.getCurrentNetwork()); } diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index f1a3fee0ea9f..bdf00e38ce94 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -174,5 +174,6 @@ public class SecureSettings { Settings.Secure.TAPS_APP_TO_EXIT, Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, Settings.Secure.PANIC_GESTURE_ENABLED, + Settings.Secure.PANIC_SOUND_ENABLED, }; } diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index 04916e2c0e2b..4ea7f3a23c10 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -262,5 +262,6 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.TAPS_APP_TO_EXIT, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.PANIC_GESTURE_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.PANIC_SOUND_ENABLED, BOOLEAN_VALIDATOR); } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index fa06e14acccb..47cc6d0fd752 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -773,29 +773,29 @@ class SettingsProtoDumpUtil { Settings.Global.GPU_DEBUG_LAYERS_GLES, GlobalSettingsProto.Gpu.DEBUG_LAYERS_GLES); dumpSetting(s, p, - Settings.Global.GAME_DRIVER_ALL_APPS, - GlobalSettingsProto.Gpu.GAME_DRIVER_ALL_APPS); + Settings.Global.UPDATABLE_DRIVER_ALL_APPS, + GlobalSettingsProto.Gpu.UPDATABLE_DRIVER_ALL_APPS); dumpSetting(s, p, - Settings.Global.GAME_DRIVER_OPT_IN_APPS, - GlobalSettingsProto.Gpu.GAME_DRIVER_OPT_IN_APPS); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS, + GlobalSettingsProto.Gpu.UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS); dumpSetting(s, p, - Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS, - GlobalSettingsProto.Gpu.GAME_DRIVER_PRERELEASE_OPT_IN_APPS); + Settings.Global.UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS, + GlobalSettingsProto.Gpu.UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS); dumpSetting(s, p, - Settings.Global.GAME_DRIVER_OPT_OUT_APPS, - GlobalSettingsProto.Gpu.GAME_DRIVER_OPT_OUT_APPS); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_OUT_APPS, + GlobalSettingsProto.Gpu.UPDATABLE_DRIVER_PRODUCTION_OPT_OUT_APPS); dumpSetting(s, p, - Settings.Global.GAME_DRIVER_DENYLIST, - GlobalSettingsProto.Gpu.GAME_DRIVER_DENYLIST); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLIST, + GlobalSettingsProto.Gpu.UPDATABLE_DRIVER_PRODUCTION_DENYLIST); dumpSetting(s, p, - Settings.Global.GAME_DRIVER_ALLOWLIST, - GlobalSettingsProto.Gpu.GAME_DRIVER_ALLOWLIST); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST, + GlobalSettingsProto.Gpu.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST); dumpSetting(s, p, - Settings.Global.GAME_DRIVER_DENYLISTS, - GlobalSettingsProto.Gpu.GAME_DRIVER_DENYLISTS); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS, + GlobalSettingsProto.Gpu.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS); dumpSetting(s, p, - Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, - GlobalSettingsProto.Gpu.GAME_DRIVER_SPHAL_LIBRARIES); + Settings.Global.UPDATABLE_DRIVER_SPHAL_LIBRARIES, + GlobalSettingsProto.Gpu.UPDATABLE_DRIVER_SPHAL_LIBRARIES); p.end(gpuToken); final long hdmiToken = p.start(GlobalSettingsProto.HDMI); @@ -2028,6 +2028,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Secure.PANIC_GESTURE_ENABLED, SecureSettingsProto.EmergencyResponse.PANIC_GESTURE_ENABLED); + dumpSetting(s, p, + Settings.Secure.PANIC_SOUND_ENABLED, + SecureSettingsProto.EmergencyResponse.PANIC_SOUND_ENABLED); p.end(emergencyResponseToken); dumpSetting(s, p, diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index 4bb8f45f331f..0ac3355c4952 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -504,14 +504,14 @@ public class SettingsBackupTest { Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS, Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES, Settings.Global.GLOBAL_SETTINGS_ANGLE_ALLOWLIST, - Settings.Global.GAME_DRIVER_ALL_APPS, - Settings.Global.GAME_DRIVER_OPT_IN_APPS, - Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS, - Settings.Global.GAME_DRIVER_OPT_OUT_APPS, - Settings.Global.GAME_DRIVER_DENYLISTS, - Settings.Global.GAME_DRIVER_DENYLIST, - Settings.Global.GAME_DRIVER_ALLOWLIST, - Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, + Settings.Global.UPDATABLE_DRIVER_ALL_APPS, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS, + Settings.Global.UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_OUT_APPS, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLIST, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST, + Settings.Global.UPDATABLE_DRIVER_SPHAL_LIBRARIES, Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX, Settings.Global.GPU_DEBUG_LAYER_APP, Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, diff --git a/packages/SoundPicker/res/values-ar/strings.xml b/packages/SoundPicker/res/values-ar/strings.xml index a91795545269..f8844e94815f 100644 --- a/packages/SoundPicker/res/values-ar/strings.xml +++ b/packages/SoundPicker/res/values-ar/strings.xml @@ -25,5 +25,5 @@ <string name="delete_ringtone_text" msgid="201443984070732499">"حذف"</string> <string name="unable_to_add_ringtone" msgid="4583511263449467326">"يتعذر إضافة نغمة رنين مخصصة"</string> <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"يتعذر حذف نغمة الرنين المخصصة"</string> - <string name="app_label" msgid="3091611356093417332">"Sounds"</string> + <string name="app_label" msgid="3091611356093417332">"الأصوات"</string> </resources> diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 98d3553287d1..4ce9f5a9edc6 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -240,6 +240,8 @@ <!-- Listen app op changes --> <uses-permission android:name="android.permission.WATCH_APPOPS" /> <uses-permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS" /> + <!-- For handling silent audio recordings --> + <uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING" /> <!-- to read and change hvac values in a car --> <uses-permission android:name="android.car.permission.CONTROL_CAR_CLIMATE" /> @@ -267,6 +269,7 @@ <!-- Permission to make accessibility service access Bubbles --> <uses-permission android:name="android.permission.ADD_TRUSTED_DISPLAY" /> + <protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" /> <protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" /> <protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" /> diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java index d2112a0ce759..883f4de1149c 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java @@ -75,11 +75,6 @@ public interface NotificationMenuRowPlugin extends Plugin { public MenuItem getLongpressMenuItem(Context context); /** - * @return the {@link MenuItem} to display when app ops icons are pressed. - */ - public MenuItem getAppOpsMenuItem(Context context); - - /** * @return the {@link MenuItem} to display when feedback icon is pressed. */ public MenuItem getFeedbackMenuItem(Context context); diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java index 0d960f0c21be..6c5c4ef94921 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java @@ -39,6 +39,10 @@ public interface StatusBarStateController { */ boolean isDozing(); + /** + * Is the status bar panel expanded. + */ + boolean isExpanded(); /** * Is device pulsing. @@ -113,5 +117,10 @@ public interface StatusBarStateController { * Callback to be notified when the pulsing state changes */ default void onPulsingChanged(boolean pulsing) {} + + /** + * Callback to be notified when the expanded state of the status bar changes + */ + default void onExpandedChanged(boolean isExpanded) {} } } diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags index 92e7d88868da..b42d71abaa6d 100644 --- a/packages/SystemUI/proguard.flags +++ b/packages/SystemUI/proguard.flags @@ -43,4 +43,6 @@ -keep class com.android.wm.shell.* --keep class com.android.systemui.dagger.GlobalRootComponent { *; }
\ No newline at end of file +-keep class com.android.systemui.dagger.GlobalRootComponent { *; } +-keep class com.android.systemui.dagger.GlobalRootComponent$SysUIComponentImpl { *; } +-keep class com.android.systemui.dagger.Dagger** { *; }
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/global_screenshot_action_chip.xml b/packages/SystemUI/res/layout/global_screenshot_action_chip.xml index 46396e3e62b4..4b3534b1cbc8 100644 --- a/packages/SystemUI/res/layout/global_screenshot_action_chip.xml +++ b/packages/SystemUI/res/layout/global_screenshot_action_chip.xml @@ -32,6 +32,7 @@ android:gravity="center"> <ImageView android:id="@+id/screenshot_action_chip_icon" + android:tint="@*android:color/accent_device_default" android:layout_width="@dimen/screenshot_action_chip_icon_size" android:layout_height="@dimen/screenshot_action_chip_icon_size" android:layout_marginStart="@dimen/screenshot_action_chip_padding_start" diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index aedbded46298..43ab1d2d4fa1 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -73,7 +73,7 @@ <string name="usb_contaminant_message" msgid="7730476585174719805">"መሣሪያዎን ከፈሳሽ ወይም ፍርስራሽ ለመጠበቅ ሲባል የዩኤስቢ ወደቡ ተሰናክሏል፣ እና ማናቸውም ተቀጥላዎችን አያገኝም።\n\nየዩኤስቢ ወደቡን እንደገና መጠቀም ችግር በማይኖረው ጊዜ ማሳወቂያ ይደርሰዎታል።"</string> <string name="usb_port_enabled" msgid="531823867664717018">"ኃይል መሙያዎችን እና ተጨማሪ መሣሪያዎችን ፈልጎ ለማግኘት የነቃ የዩኤስቢ ወደብ"</string> <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"ዩኤስቢ አንቃ"</string> - <string name="learn_more" msgid="4690632085667273811">"የበለጠ መረዳት"</string> + <string name="learn_more" msgid="4690632085667273811">"የበለጠ ለመረዳት"</string> <string name="compat_mode_on" msgid="4963711187149440884">"ማያ እንዲሞላ አጉላ"</string> <string name="compat_mode_off" msgid="7682459748279487945">"ማያ ለመሙለት ሳብ"</string> <string name="global_action_screenshot" msgid="2760267567509131654">"ቅጽበታዊ ገጽ እይታ"</string> @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index fee86ca42fe6..c68d0887e425 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -1093,8 +1093,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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index 3778df80197b..d604fd47c4fd 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -125,7 +125,7 @@ <string name="accessibility_accessibility_button" msgid="4089042473497107709">"দিব্যাংগসকলৰ বাবে থকা সুবিধাসমূহ"</string> <string name="accessibility_rotate_button" msgid="1238584767612362586">"স্ক্ৰীণ ঘূৰাওক"</string> <string name="accessibility_recent" msgid="901641734769533575">"অৱলোকন"</string> - <string name="accessibility_search_light" msgid="524741790416076988">"সন্ধান কৰক"</string> + <string name="accessibility_search_light" msgid="524741790416076988">"Search"</string> <string name="accessibility_camera_button" msgid="2938898391716647247">"কেমেৰা"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ফ\'ন"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"কণ্ঠধ্বনিৰে সহায়"</string> @@ -441,7 +441,7 @@ <string name="expanded_header_battery_charging_with_time" msgid="757991461445765011">"বেটাৰিৰ চ্চাৰ্জ সম্পূর্ণ হ\'বলৈ <xliff:g id="CHARGING_TIME">%s</xliff:g> বাকী"</string> <string name="expanded_header_battery_not_charging" msgid="809409140358955848">"চ্চার্জ কৰি থকা নাই"</string> <string name="ssl_ca_cert_warning" msgid="8373011375250324005">"নেটৱৰ্ক \nনিৰীক্ষণ কৰা হ\'ব পাৰে"</string> - <string name="description_target_search" msgid="3875069993128855865">"অনুসন্ধান কৰক"</string> + <string name="description_target_search" msgid="3875069993128855865">"Search"</string> <string name="description_direction_up" msgid="3632251507574121434">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>ৰ বাবে ওপৰলৈ শ্লাইড কৰক।"</string> <string name="description_direction_left" msgid="4762708739096907741">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>ৰ বাবে বাওঁফাললৈ শ্লাইড কৰক।"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"আপুনি নিৰ্দিষ্ট কৰা এলাৰ্ম, ৰিমাইণ্ডাৰ, ইভেন্ট আৰু কল কৰোঁতাৰ বাহিৰে আন কোনো শব্দৰ পৰা আপুনি অসুবিধা নাপাব। কিন্তু, সংগীত, ভিডিঅ\' আৰু খেলসমূহকে ধৰি আপুনি প্লে কৰিব খোজা যিকোনো বস্তু তথাপি শুনিব পাৰিব।"</string> @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 874bf7465827..b1df2522a513 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"İmtina edin"</string> <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 2a120c57e955..f3c4c6b8487d 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -1075,8 +1075,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Odbaci"</string> <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 e4bb67ae65c6..9c0eeb206e9e 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -1081,8 +1081,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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index c51e58ccd6cf..3bf12ad06f1a 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 3d00ca858ef5..5b7c953d5692 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -125,7 +125,7 @@ <string name="accessibility_accessibility_button" msgid="4089042473497107709">"অ্যাক্সেসযোগ্যতা"</string> <string name="accessibility_rotate_button" msgid="1238584767612362586">"স্ক্রিন ঘোরান"</string> <string name="accessibility_recent" msgid="901641734769533575">"এক নজরে"</string> - <string name="accessibility_search_light" msgid="524741790416076988">"খুঁজুন"</string> + <string name="accessibility_search_light" msgid="524741790416076988">"সার্চ"</string> <string name="accessibility_camera_button" msgid="2938898391716647247">"ক্যামেরা"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ফোন"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ভয়েস সহায়তা"</string> @@ -441,7 +441,7 @@ <string name="expanded_header_battery_charging_with_time" msgid="757991461445765011">"পূর্ণ হতে <xliff:g id="CHARGING_TIME">%s</xliff:g> সময় লাগবে"</string> <string name="expanded_header_battery_not_charging" msgid="809409140358955848">"চার্জ হচ্ছে না"</string> <string name="ssl_ca_cert_warning" msgid="8373011375250324005">"নেটওয়ার্ক নিরীক্ষণ\nকরা হতে পারে"</string> - <string name="description_target_search" msgid="3875069993128855865">"খুঁজুন"</string> + <string name="description_target_search" msgid="3875069993128855865">"সার্চ"</string> <string name="description_direction_up" msgid="3632251507574121434">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> এর জন্য উপরের দিকে স্লাইড করুন৷"</string> <string name="description_direction_left" msgid="4762708739096907741">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> এর জন্য বাঁ দিকে স্লাইড করুন৷"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"অ্যালার্ম, রিমাইন্ডার, ইভেন্ট, এবং আপনার নির্দিষ্ট করে দেওয়া ব্যক্তিদের কল ছাড়া অন্য কোনও আওয়াজ বা ভাইব্রেশন হবে না। তবে সঙ্গীত, ভিডিও, এবং গেম সহ আপনি যা কিছু চালাবেন তার আওয়াজ শুনতে পাবেন।"</string> @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 14259840d503..31f88c8fbd24 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -1075,8 +1075,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Odbaci"</string> <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 b1501558f924..753e25f13420 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignora"</string> <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 ae6cc13cd1df..039500d2a4f4 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -1081,8 +1081,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Zavřít"</string> <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 09f7f1a8762e..0c8a5b75c9e6 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Luk"</string> <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 2410e4785c8d..1c4c7ab229f9 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ablehnen"</string> <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> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index f66c5a88b102..07ff80706b33 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 45e072496b25..38fa52874512 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Descartar"</string> <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 f7ebbd02708a..10aa6cac7c2a 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Cerrar"</string> <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 1e5e49e0a143..9122ce5c4c0d 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Loobu"</string> <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-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index fa076c4fc40e..52e5e8cf29d6 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ohita"</string> <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 9c418f79a075..4797f323b5d5 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Fermer"</string> <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 3e2f5fdbff1d..e5df728c34c6 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Fermer"</string> <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 9ecd75e80a4c..246fefd316db 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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">"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 6e05a540a13e..beaacaa1c073 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -125,7 +125,7 @@ <string name="accessibility_accessibility_button" msgid="4089042473497107709">"ઍક્સેસિબિલિટી"</string> <string name="accessibility_rotate_button" msgid="1238584767612362586">"સ્ક્રીન ફેરવો"</string> <string name="accessibility_recent" msgid="901641734769533575">"ઝલક"</string> - <string name="accessibility_search_light" msgid="524741790416076988">"શોધો"</string> + <string name="accessibility_search_light" msgid="524741790416076988">"શોધ"</string> <string name="accessibility_camera_button" msgid="2938898391716647247">"કૅમેરો"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ફોન"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"વૉઇસ સહાય"</string> @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 4bebe79c3c44..7bf0b93b9bcb 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -1075,8 +1075,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Odbaci"</string> <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 42e251fb39de..875a05f71453 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Elvetés"</string> <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 e6b71395c42a..4cc406bf9af7 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index fec4205ba7da..5f7dce43925a 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Tutup"</string> <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 3a9e63ba9f1a..b5f6e57002df 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Hunsa"</string> <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 3eca501b103c..f4453b76bb61 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignora"</string> <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 e88c951cf19e..161fedc7a41e 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -1081,8 +1081,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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 130f682daaf3..fa9c040b29a9 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index d050875c35ce..a3ddf70b5b25 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index 36c726edb791..0d3f7f9f1973 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 9d87c583c007..5abd74000af5 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 901f024c5f71..47f23856c7b0 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -125,7 +125,7 @@ <string name="accessibility_accessibility_button" msgid="4089042473497107709">"ಪ್ರವೇಶಿಸುವಿಕೆ"</string> <string name="accessibility_rotate_button" msgid="1238584767612362586">"ಪರದೆಯನ್ನು ತಿರುಗಿಸಿ"</string> <string name="accessibility_recent" msgid="901641734769533575">"ಸಮಗ್ರ ನೋಟ"</string> - <string name="accessibility_search_light" msgid="524741790416076988">"ಹುಡುಕಿ"</string> + <string name="accessibility_search_light" msgid="524741790416076988">"Search"</string> <string name="accessibility_camera_button" msgid="2938898391716647247">"ಕ್ಯಾಮರಾ"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ಫೋನ್"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ಧ್ವನಿ ಸಹಾಯಕ"</string> @@ -441,7 +441,7 @@ <string name="expanded_header_battery_charging_with_time" msgid="757991461445765011">"<xliff:g id="CHARGING_TIME">%s</xliff:g> ಪೂರ್ಣಗೊಳ್ಳುವವರೆಗೆ"</string> <string name="expanded_header_battery_not_charging" msgid="809409140358955848">"ಚಾರ್ಜ್ ಆಗುತ್ತಿಲ್ಲ"</string> <string name="ssl_ca_cert_warning" msgid="8373011375250324005">"ನೆಟ್ವರ್ಕ್\n ವೀಕ್ಷಿಸಬಹುದಾಗಿರುತ್ತದೆ"</string> - <string name="description_target_search" msgid="3875069993128855865">"ಹುಡುಕಿ"</string> + <string name="description_target_search" msgid="3875069993128855865">"Search"</string> <string name="description_direction_up" msgid="3632251507574121434">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ಗಾಗಿ ಮೇಲಕ್ಕೆ ಸ್ಲೈಡ್ ಮಾಡಿ."</string> <string name="description_direction_left" msgid="4762708739096907741">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ಗಾಗಿ ಎಡಕ್ಕೆ ಸ್ಲೈಡ್ ಮಾಡಿ."</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"ಅಲಾರಾಂಗಳು, ಜ್ಞಾಪನೆಗಳು, ಈವೆಂಟ್ಗಳು ಹಾಗೂ ನೀವು ಸೂಚಿಸಿರುವ ಕರೆದಾರರನ್ನು ಹೊರತುಪಡಿಸಿ ಬೇರಾವುದೇ ಸದ್ದುಗಳು ಅಥವಾ ವೈಬ್ರೇಶನ್ಗಳು ನಿಮಗೆ ತೊಂದರೆ ನೀಡುವುದಿಲ್ಲ. ಹಾಗಿದ್ದರೂ, ನೀವು ಪ್ಲೇ ಮಾಡುವ ಸಂಗೀತ, ವೀಡಿಯೊಗಳು ಮತ್ತು ಆಟಗಳ ಆಡಿಯೊವನ್ನು ನೀವು ಕೇಳಿಸಿಕೊಳ್ಳುತ್ತೀರಿ."</string> @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 8a6415566676..beb7edade8e6 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -502,10 +502,10 @@ <string name="battery_saver_notification_title" msgid="8419266546034372562">"절전 모드 사용 중"</string> <string name="battery_saver_notification_text" msgid="2617841636449016951">"성능 및 백그라운드 데이터를 줄입니다."</string> <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"절전 모드 사용 중지"</string> - <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>이(가) 녹화 또는 전송 중에 화면에 표시되거나 기기에서 재생되는 모든 정보에 액세스할 수 있습니다. 여기에는 비밀번호, 결제 세부정보, 사진, 메시지, 재생하는 오디오 같은 정보가 포함됩니다."</string> + <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>이 녹화 또는 전송 중에 화면에 표시되거나 기기에서 재생되는 모든 정보에 액세스할 수 있습니다. 여기에는 비밀번호, 결제 세부정보, 사진, 메시지, 재생하는 오디오 같은 정보가 포함됩니다."</string> <string name="media_projection_dialog_service_text" msgid="958000992162214611">"이 기능을 제공하는 서비스는 녹화 또는 전송 중에 화면에 표시되거나 기기에서 재생되는 모든 정보에 액세스할 수 있습니다. 여기에는 비밀번호, 결제 세부정보, 사진, 메시지, 재생하는 오디오 같은 정보가 포함됩니다."</string> <string name="media_projection_dialog_service_title" msgid="2888507074107884040">"녹화 또는 전송을 시작하시겠습니까?"</string> - <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>(으)로 녹화 또는 전송을 시작하시겠습니까?"</string> + <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>으로 녹화 또는 전송을 시작하시겠습니까?"</string> <string name="media_projection_remember_text" msgid="6896767327140422951">"다시 표시 안함"</string> <string name="clear_all_notifications_text" msgid="348312370303046130">"모두 지우기"</string> <string name="manage_notifications_text" msgid="6885645344647733116">"관리"</string> @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 3cf41264a4d4..4fbb09e56bbd 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index b1c5a5cd887e..6d7feabfed1a 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 4e9b802f4916..21217a06179f 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -1081,8 +1081,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Atsisakyti"</string> <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 a4c4666fafe3..4945dfa3f3db 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -1075,8 +1075,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Nerādīt"</string> <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 7e623ad5032f..40d4698f7c21 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 35e642769981..c3bd65ef8e50 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -125,7 +125,7 @@ <string name="accessibility_accessibility_button" msgid="4089042473497107709">"ഉപയോഗസഹായി"</string> <string name="accessibility_rotate_button" msgid="1238584767612362586">"സ്ക്രീൻ തിരിക്കുക"</string> <string name="accessibility_recent" msgid="901641734769533575">"അവലോകനം"</string> - <string name="accessibility_search_light" msgid="524741790416076988">"തിരയൽ"</string> + <string name="accessibility_search_light" msgid="524741790416076988">"Search"</string> <string name="accessibility_camera_button" msgid="2938898391716647247">"ക്യാമറ"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ഫോണ്"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"വോയ്സ് സഹായം"</string> @@ -441,7 +441,7 @@ <string name="expanded_header_battery_charging_with_time" msgid="757991461445765011">"ഫുൾ ചാർജാകാൻ, <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string> <string name="expanded_header_battery_not_charging" msgid="809409140358955848">"ചാർജ്ജുചെയ്യുന്നില്ല"</string> <string name="ssl_ca_cert_warning" msgid="8373011375250324005">"നെറ്റ്വർക്ക്\nനിരീക്ഷിക്കപ്പെടാം"</string> - <string name="description_target_search" msgid="3875069993128855865">"തിരയൽ"</string> + <string name="description_target_search" msgid="3875069993128855865">"Search"</string> <string name="description_direction_up" msgid="3632251507574121434">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> എന്നതിനായി മുകളിലേയ്ക്ക് സ്ലൈഡുചെയ്യുക."</string> <string name="description_direction_left" msgid="4762708739096907741">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> എന്നതിനായി ഇടത്തേയ്ക്ക് സ്ലൈഡുചെയ്യുക."</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"നിങ്ങൾ സജ്ജീകരിച്ച അലാറങ്ങൾ, റിമൈൻഡറുകൾ, ഇവന്റുകൾ, കോളർമാർ എന്നിവയിൽ നിന്നുള്ള ശബ്ദങ്ങളും വൈബ്രേഷനുകളുമൊഴികെ മറ്റൊന്നും നിങ്ങളെ ശല്യപ്പെടുത്തുകയില്ല. സംഗീതം, വീഡിയോകൾ, ഗെയിമുകൾ എന്നിവയുൾപ്പെടെ പ്ലേ ചെയ്യുന്നതെന്തും നിങ്ങൾക്ക് തുടർന്നും കേൾക്കാൻ കഴിയും."</string> @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index b4690d418480..5f08f05ed9be 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index 4ea965ad80fc..6d525df2d05b 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -125,7 +125,7 @@ <string name="accessibility_accessibility_button" msgid="4089042473497107709">"अॅक्सेसिबिलिटी"</string> <string name="accessibility_rotate_button" msgid="1238584767612362586">"स्क्रीन फिरवा"</string> <string name="accessibility_recent" msgid="901641734769533575">"अवलोकन"</string> - <string name="accessibility_search_light" msgid="524741790416076988">"शोधा"</string> + <string name="accessibility_search_light" msgid="524741790416076988">"Search"</string> <string name="accessibility_camera_button" msgid="2938898391716647247">"कॅमेरा"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"फोन"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"व्हॉइस सहाय्य"</string> @@ -441,7 +441,7 @@ <string name="expanded_header_battery_charging_with_time" msgid="757991461445765011">"<xliff:g id="CHARGING_TIME">%s</xliff:g> पूर्ण होईपर्यंत"</string> <string name="expanded_header_battery_not_charging" msgid="809409140358955848">"चार्ज होत नाही"</string> <string name="ssl_ca_cert_warning" msgid="8373011375250324005">"नेटवर्कचे परीक्षण\nकेले जाऊ शकते"</string> - <string name="description_target_search" msgid="3875069993128855865">"शोध"</string> + <string name="description_target_search" msgid="3875069993128855865">"Search"</string> <string name="description_direction_up" msgid="3632251507574121434">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> साठी वर स्लाइड करा."</string> <string name="description_direction_left" msgid="4762708739096907741">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> साठी डावीकडे स्लाइड करा."</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"अलार्म, रिमाइंडर, इव्हेंट आणि तुम्ही निश्चित केलेल्या कॉलर व्यतिरिक्त तुम्हाला कोणत्याही आवाज आणि कंपनांचा व्यत्त्यय आणला जाणार नाही. तरीही तुम्ही प्ले करायचे ठरवलेले कोणतेही संगीत, व्हिडिओ आणि गेमचे आवाज ऐकू शकतात."</string> @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 38ee25c7f3e4..4f832e4c450d 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Tolak"</string> <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-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index d872a89880c9..849c2e9e7381 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Lukk"</string> <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 1974e8088971..2ac442ec0225 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 9da8afa4d698..da0f42754acd 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Sluiten"</string> <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 5b5cbc62fe21..029aa69b6fbf 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -125,7 +125,7 @@ <string name="accessibility_accessibility_button" msgid="4089042473497107709">"ଆକ୍ସେସିବିଲିଟୀ"</string> <string name="accessibility_rotate_button" msgid="1238584767612362586">"ସ୍କ୍ରୀନ୍କୁ ଘୁରାନ୍ତୁ"</string> <string name="accessibility_recent" msgid="901641734769533575">"ଓଭରଭିଉ"</string> - <string name="accessibility_search_light" msgid="524741790416076988">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string> + <string name="accessibility_search_light" msgid="524741790416076988">"Search"</string> <string name="accessibility_camera_button" msgid="2938898391716647247">"କ୍ୟାମେରା"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ଫୋନ୍"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ଭଏସ୍ ସହାୟକ"</string> @@ -441,7 +441,7 @@ <string name="expanded_header_battery_charging_with_time" msgid="757991461445765011">"ପୂର୍ଣ୍ଣ ଚାର୍ଜ ହେବାକୁ ଆଉ <xliff:g id="CHARGING_TIME">%s</xliff:g> ଅଛି"</string> <string name="expanded_header_battery_not_charging" msgid="809409140358955848">"ଚାର୍ଜ ହେଉନାହିଁ"</string> <string name="ssl_ca_cert_warning" msgid="8373011375250324005">"ନେଟ୍ୱର୍କ\nମନିଟର୍ କରାଯାଇପାରେ"</string> - <string name="description_target_search" msgid="3875069993128855865">"ସର୍ଚ୍ଚ"</string> + <string name="description_target_search" msgid="3875069993128855865">"Search"</string> <string name="description_direction_up" msgid="3632251507574121434">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ପାଇଁ ଉପରକୁ ସ୍ଲାଇଡ୍ କରନ୍ତୁ।"</string> <string name="description_direction_left" msgid="4762708739096907741">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ପାଇଁ ବାମକୁ ସ୍ଲାଇଡ୍ କରନ୍ତୁ"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"ଆଲାର୍ମ, ରିମାଇଣ୍ଡର୍, ଇଭେଣ୍ଟ ଏବଂ ଆପଣ ନିର୍ଦ୍ଦିଷ୍ଟ କରିଥିବା କଲର୍ଙ୍କ ବ୍ୟତୀତ ଆପଣଙ୍କ ଧ୍ୟାନ ଅନ୍ୟ କୌଣସି ଧ୍ୱନୀ ଏବଂ ଭାଇବ୍ରେଶନ୍ରେ ଆକର୍ଷଣ କରାଯିବନାହିଁ। ମ୍ୟୁଜିକ୍, ଭିଡିଓ ଏବଂ ଗେମ୍ ସମେତ ନିଜେ ଚଲାଇବାକୁ ବାଛିଥିବା ଅନ୍ୟ ସବୁକିଛି ଆପଣ ଶୁଣିପାରିବେ।"</string> @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 5c31ce71ef98..ed5f40caf7d0 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index b7ee75057626..ba30cedd9e39 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -1081,8 +1081,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Odrzuć"</string> <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-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 49c3ba0c2cd8..cf428a39d4a7 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -1075,8 +1075,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Închideți"</string> <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 7fb456d5f425..ba86e9501006 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -1081,8 +1081,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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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 9d7e7d1cd27c..75486073fd5e 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -1081,8 +1081,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Zavrieť"</string> <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 ecbf1d905e5b..07ad8c1ca99e 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -1081,8 +1081,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Opusti"</string> <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 70245b875726..b92744d7f087 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Hiq"</string> <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 1d02ca6ab455..f57d92bb911e 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -1075,8 +1075,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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 7a7448be16c5..876e3377171c 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Stäng"</string> <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 b8d95fcd0c1a..25e349367b52 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ondoa"</string> <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 60c1cf9dcac0..19e67db62de8 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 6cfe03d95023..34ff9b102da0 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -125,7 +125,7 @@ <string name="accessibility_accessibility_button" msgid="4089042473497107709">"యాక్సెస్ సామర్థ్యం"</string> <string name="accessibility_rotate_button" msgid="1238584767612362586">"స్క్రీన్ను తిప్పండి"</string> <string name="accessibility_recent" msgid="901641734769533575">"ఓవర్వ్యూ"</string> - <string name="accessibility_search_light" msgid="524741790416076988">"వెతుకు"</string> + <string name="accessibility_search_light" msgid="524741790416076988">"సెర్చ్"</string> <string name="accessibility_camera_button" msgid="2938898391716647247">"కెమెరా"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ఫోన్"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"వాయిస్ అసిస్టెంట్"</string> @@ -441,7 +441,7 @@ <string name="expanded_header_battery_charging_with_time" msgid="757991461445765011">"పూర్తిగా నిండటానికి <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string> <string name="expanded_header_battery_not_charging" msgid="809409140358955848">"ఛార్జ్ కావడం లేదు"</string> <string name="ssl_ca_cert_warning" msgid="8373011375250324005">"నెట్వర్క్\nపర్యవేక్షించబడవచ్చు"</string> - <string name="description_target_search" msgid="3875069993128855865">"శోధించండి"</string> + <string name="description_target_search" msgid="3875069993128855865">"సెర్చ్"</string> <string name="description_direction_up" msgid="3632251507574121434">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> కోసం పైకి స్లైడ్ చేయండి."</string> <string name="description_direction_left" msgid="4762708739096907741">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> కోసం ఎడమవైపుకు స్లైడ్ చేయండి."</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"మీరు పేర్కొనే అలారాలు, రిమైండర్లు, ఈవెంట్లు మరియు కాలర్ల నుండి మినహా మరే ఇతర ధ్వనులు మరియు వైబ్రేషన్లతో మీకు అంతరాయం కలగదు. మీరు ఇప్పటికీ సంగీతం, వీడియోలు మరియు గేమ్లతో సహా మీరు ప్లే చేయడానికి ఎంచుకున్నవి ఏవైనా వింటారు."</string> @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index a2c1127df5ca..d37be57e0136 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index e5f0532b0e7b..af474c761fc5 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"I-dismiss"</string> <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 4943e2d03920..ee494a25e366 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Kapat"</string> <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 447912e08835..c444c47d1441 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -1081,8 +1081,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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 20b551882344..729ed5a3ac51 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index a12a08d0a1e6..5794bdf3c8eb 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Đóng"</string> <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 3382365b7ccb..41c132c9faf6 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 1d55ca22a43f..b2e1b90de007 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index e62c164684b3..346b1239cf0f 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -1069,8 +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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <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-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index bd7391203dd8..5abce7fb4415 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -1069,8 +1069,7 @@ <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> - <!-- no translation found for controls_media_dismiss_button (9081375542265132213) --> - <skip /> + <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Cashisa"</string> <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/config_tv.xml b/packages/SystemUI/res/values/config_tv.xml index 5cb840f24c84..7451ba8e88a4 100644 --- a/packages/SystemUI/res/values/config_tv.xml +++ b/packages/SystemUI/res/values/config_tv.xml @@ -22,9 +22,4 @@ <!-- Whether to enable microphone disclosure indicator (com.android.systemui.statusbar.tv.micdisclosure.AudioRecordingDisclosureBar). --> <bool name="audio_recording_disclosure_enabled">true</bool> - - <!-- Whether the indicator should expand and show the recording application's label. - When disabled (false) the "minimized" indicator would appear on the screen whenever an - application is recording, but will not reveal to the user what application this is. --> - <bool name="audio_recording_disclosure_reveal_packages">false</bool> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 122fcb21a9f4..765a9422585a 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1036,6 +1036,11 @@ <!-- The maximum offset in either direction that icons move to prevent burn-in on AOD. --> <dimen name="default_burn_in_prevention_offset">15dp</dimen> + <!-- The maximum offset for the under-display fingerprint sensor (UDFPS) icon in either + direction that elements aer moved to prevent burn-in on AOD--> + <dimen name="udfps_burn_in_offset_x">8dp</dimen> + <dimen name="udfps_burn_in_offset_y">8dp</dimen> + <dimen name="corner_size">8dp</dimen> <dimen name="top_padding">0dp</dimen> <dimen name="bottom_padding">48dp</dimen> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 5f00a591860e..b0483339d14e 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -256,7 +256,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe mUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class); mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y); mInjectionInflationController = new InjectionInflationController( - SystemUIFactory.getInstance().getRootComponent().createViewInstanceCreatorFactory()); + SystemUIFactory.getInstance().getSysUIComponent().createViewInstanceCreatorFactory()); mViewConfiguration = ViewConfiguration.get(context); mKeyguardStateController = Dependency.get(KeyguardStateController.class); mSecondaryLockScreenController = new AdminSecondaryLockScreenController(context, this, diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java index 17abfae3c7e1..ac2160ecb4ae 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java @@ -24,11 +24,11 @@ import android.telephony.TelephonyManager; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.Dependency; +import com.android.systemui.dagger.SysUISingleton; import javax.inject.Inject; -import javax.inject.Singleton; -@Singleton +@SysUISingleton public class KeyguardSecurityModel { /** diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 878947f6ba37..c354241da7b4 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -94,6 +94,7 @@ import com.android.systemui.DejankUtils; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; @@ -124,14 +125,13 @@ import java.util.concurrent.Executor; import java.util.function.Consumer; import javax.inject.Inject; -import javax.inject.Singleton; /** * Watches for updates that may be interesting to the keyguard, and provides * the up to date information as well as a registration for callbacks that care * to be updated. */ -@Singleton +@SysUISingleton public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpable { private static final String TAG = "KeyguardUpdateMonitor"; diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java index 2200b22b8b27..3775628df0e0 100644 --- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java +++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java @@ -34,6 +34,7 @@ import androidx.lifecycle.Observer; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dock.DockManager; import com.android.systemui.dock.DockManager.DockEventListener; import com.android.systemui.plugins.ClockPlugin; @@ -50,12 +51,11 @@ import java.util.Objects; import java.util.function.Supplier; import javax.inject.Inject; -import javax.inject.Singleton; /** * Manages custom clock faces for AOD and lock screen. */ -@Singleton +@SysUISingleton public final class ClockManager { private static final String TAG = "ClockOptsProvider"; diff --git a/packages/SystemUI/src/com/android/systemui/ActivityIntentHelper.java b/packages/SystemUI/src/com/android/systemui/ActivityIntentHelper.java index 63840bcb293a..43b3929808b3 100644 --- a/packages/SystemUI/src/com/android/systemui/ActivityIntentHelper.java +++ b/packages/SystemUI/src/com/android/systemui/ActivityIntentHelper.java @@ -22,15 +22,16 @@ import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import com.android.systemui.dagger.SysUISingleton; + import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * Contains useful methods for querying properties of an Activity Intent. */ -@Singleton +@SysUISingleton public class ActivityIntentHelper { private final Context mContext; diff --git a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java index 47a10af7c550..3d6d38149fc5 100644 --- a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java @@ -18,13 +18,13 @@ import android.app.PendingIntent; import android.content.Intent; import android.view.View; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.phone.StatusBar; import java.util.Optional; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; @@ -33,7 +33,7 @@ import dagger.Lazy; * delegates to an actual implementation (StatusBar). */ @SuppressWarnings("OptionalUsedAsFieldOrParameterType") -@Singleton +@SysUISingleton public class ActivityStarterDelegate implements ActivityStarter { private Optional<Lazy<StatusBar>> mActualStarter; diff --git a/packages/SystemUI/src/com/android/systemui/BootCompleteCacheImpl.kt b/packages/SystemUI/src/com/android/systemui/BootCompleteCacheImpl.kt index aef1872f6520..9eaf4c96c896 100644 --- a/packages/SystemUI/src/com/android/systemui/BootCompleteCacheImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/BootCompleteCacheImpl.kt @@ -18,13 +18,13 @@ package com.android.systemui import android.util.Log import com.android.internal.annotations.GuardedBy +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dump.DumpManager import java.io.FileDescriptor import java.io.PrintWriter import java.lang.ref.WeakReference import java.util.concurrent.atomic.AtomicBoolean import javax.inject.Inject -import javax.inject.Singleton /** * Caches whether the device has reached [SystemService.PHASE_BOOT_COMPLETED]. @@ -32,7 +32,7 @@ import javax.inject.Singleton * This class is constructed and set by [SystemUIApplication] and will notify all listeners when * boot is completed. */ -@Singleton +@SysUISingleton class BootCompleteCacheImpl @Inject constructor(dumpManager: DumpManager) : BootCompleteCache, Dumpable { diff --git a/packages/SystemUI/src/com/android/systemui/DemoMode.java b/packages/SystemUI/src/com/android/systemui/DemoMode.java deleted file mode 100644 index 5c3971571b87..000000000000 --- a/packages/SystemUI/src/com/android/systemui/DemoMode.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 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; - -import android.os.Bundle; - -public interface DemoMode { - - public static final String DEMO_MODE_ALLOWED = "sysui_demo_allowed"; - - void dispatchDemoCommand(String command, Bundle args); - - public static final String ACTION_DEMO = "com.android.systemui.demo"; - - public static final String EXTRA_COMMAND = "command"; - - public static final String COMMAND_ENTER = "enter"; - public static final String COMMAND_EXIT = "exit"; - public static final String COMMAND_CLOCK = "clock"; - public static final String COMMAND_BATTERY = "battery"; - public static final String COMMAND_NETWORK = "network"; - public static final String COMMAND_BARS = "bars"; - public static final String COMMAND_STATUS = "status"; - public static final String COMMAND_NOTIFICATIONS = "notifications"; - public static final String COMMAND_VOLUME = "volume"; - public static final String COMMAND_OPERATOR = "operator"; -} diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index 10f2069087d5..748a9c9448c5 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -39,6 +39,7 @@ import com.android.systemui.assist.AssistManager; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dock.DockManager; @@ -47,6 +48,8 @@ import com.android.systemui.fragments.FragmentService; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.model.SysUiState; +import com.android.systemui.navigationbar.NavigationBarController; +import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.PluginDependencyProvider; @@ -64,18 +67,18 @@ import com.android.systemui.shared.system.DevicePolicyManagerWrapper; import com.android.systemui.shared.system.PackageManagerWrapper; import com.android.systemui.stackdivider.Divider; import com.android.systemui.statusbar.CommandQueue; -import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationRemoteInputManager; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationViewHierarchyManager; import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment; import com.android.systemui.statusbar.notification.NotificationFilter; -import com.android.systemui.statusbar.notification.VisualStabilityManager; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; @@ -85,10 +88,8 @@ import com.android.systemui.statusbar.phone.KeyguardDismissUtil; import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.statusbar.phone.LockscreenGestureLogger; import com.android.systemui.statusbar.phone.ManagedProfileController; -import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper; import com.android.systemui.statusbar.phone.NotificationGroupManager; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarIconController; @@ -131,7 +132,6 @@ import java.util.function.Consumer; import javax.inject.Inject; import javax.inject.Named; -import javax.inject.Singleton; import dagger.Lazy; @@ -150,7 +150,7 @@ import dagger.Lazy; * they have no clients they should not have any registered resources like bound * services, registered receivers, etc. */ -@Singleton +@SysUISingleton public class Dependency { /** * Key for getting a the main looper. diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java index 2deeb1230f09..d859a63d0943 100644 --- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java +++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java @@ -24,36 +24,26 @@ import android.util.SparseArray; import com.android.internal.messages.nano.SystemMessageProto; import com.android.systemui.appops.AppOpsController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.util.Assert; -import java.util.Set; - import javax.inject.Inject; -import javax.inject.Singleton; /** * Tracks state of foreground services and notifications related to foreground services per user. */ -@Singleton +@SysUISingleton public class ForegroundServiceController { - public static final int[] APP_OPS = new int[] {AppOpsManager.OP_CAMERA, - AppOpsManager.OP_SYSTEM_ALERT_WINDOW, - AppOpsManager.OP_RECORD_AUDIO, - AppOpsManager.OP_COARSE_LOCATION, - AppOpsManager.OP_FINE_LOCATION}; + public static final int[] APP_OPS = new int[] {AppOpsManager.OP_SYSTEM_ALERT_WINDOW}; private final SparseArray<ForegroundServicesUserState> mUserServices = new SparseArray<>(); private final Object mMutex = new Object(); - private final NotificationEntryManager mEntryManager; private final Handler mMainHandler; @Inject - public ForegroundServiceController(NotificationEntryManager entryManager, - AppOpsController appOpsController, @Main Handler mainHandler) { - mEntryManager = entryManager; + public ForegroundServiceController(AppOpsController appOpsController, + @Main Handler mainHandler) { mMainHandler = mainHandler; appOpsController.addCallback(APP_OPS, (code, uid, packageName, active) -> { mMainHandler.post(() -> { @@ -87,19 +77,6 @@ public class ForegroundServiceController { } /** - * Returns the keys for notifications from this package using the standard template, - * if they exist. - */ - @Nullable - public ArraySet<String> getStandardLayoutKeys(int userId, String pkg) { - synchronized (mMutex) { - final ForegroundServicesUserState services = mUserServices.get(userId); - if (services == null) return null; - return services.getStandardLayoutKeys(pkg); - } - } - - /** * Gets active app ops for this user and package */ @Nullable @@ -140,31 +117,6 @@ public class ForegroundServiceController { userServices.removeOp(packageName, appOpCode); } } - - // TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by - // AppOpsCoordinator - // Update appOps if there are associated pending or visible notifications - final Set<String> notificationKeys = getStandardLayoutKeys(userId, packageName); - if (notificationKeys != null) { - boolean changed = false; - for (String key : notificationKeys) { - final NotificationEntry entry = mEntryManager.getPendingOrActiveNotif(key); - if (entry != null - && uid == entry.getSbn().getUid() - && packageName.equals(entry.getSbn().getPackageName())) { - synchronized (entry.mActiveAppOps) { - if (active) { - changed |= entry.mActiveAppOps.add(appOpCode); - } else { - changed |= entry.mActiveAppOps.remove(appOpCode); - } - } - } - } - if (changed) { - mEntryManager.updateNotifications("appOpChanged pkg=" + packageName); - } - } } /** diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java index bb445832da93..d6cb1142061d 100644 --- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java +++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java @@ -21,10 +21,10 @@ import android.app.NotificationManager; import android.content.Context; import android.os.Bundle; import android.service.notification.StatusBarNotification; -import android.util.ArraySet; import android.util.Log; import com.android.internal.statusbar.NotificationVisibility; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotifPipeline; @@ -33,10 +33,9 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.No import com.android.systemui.util.time.SystemClock; import javax.inject.Inject; -import javax.inject.Singleton; /** Updates foreground service notification state in response to notification data events. */ -@Singleton +@SysUISingleton public class ForegroundServiceNotificationListener { private static final String TAG = "FgServiceController"; @@ -172,24 +171,8 @@ public class ForegroundServiceNotificationListener { sbn.getPackageName(), sbn.getKey()); } } - tagAppOps(entry); return true; }, true /* create if not found */); } - - // TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by - // AppOpsCoordinator - private void tagAppOps(NotificationEntry entry) { - final StatusBarNotification sbn = entry.getSbn(); - ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps( - sbn.getUserId(), - sbn.getPackageName()); - synchronized (entry.mActiveAppOps) { - entry.mActiveAppOps.clear(); - if (activeOps != null) { - entry.mActiveAppOps.addAll(activeOps); - } - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/InitController.java b/packages/SystemUI/src/com/android/systemui/InitController.java index a2dd12389fa9..9bb576b1f3dd 100644 --- a/packages/SystemUI/src/com/android/systemui/InitController.java +++ b/packages/SystemUI/src/com/android/systemui/InitController.java @@ -14,16 +14,17 @@ package com.android.systemui; +import com.android.systemui.dagger.SysUISingleton; + import java.util.ArrayList; import javax.inject.Inject; -import javax.inject.Singleton; /** * Created by {@link Dependency} on SystemUI startup. Add tasks which need to be executed only * after all other dependencies have been created. */ -@Singleton +@SysUISingleton public class InitController { /** diff --git a/packages/SystemUI/src/com/android/systemui/LatencyTester.java b/packages/SystemUI/src/com/android/systemui/LatencyTester.java index dc0cb03e9b23..9c5a40c22bd8 100644 --- a/packages/SystemUI/src/com/android/systemui/LatencyTester.java +++ b/packages/SystemUI/src/com/android/systemui/LatencyTester.java @@ -30,16 +30,16 @@ import android.os.SystemClock; import com.android.internal.util.LatencyTracker; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.phone.BiometricUnlockController; import javax.inject.Inject; -import javax.inject.Singleton; /** * Class that only runs on debuggable builds that listens to broadcasts that simulate actions in the * system that are used for testing the latency. */ -@Singleton +@SysUISingleton public class LatencyTester extends SystemUI { private static final String diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index ad11d71eb132..f663d1a0d77c 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -83,6 +83,7 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.util.Preconditions; import com.android.systemui.RegionInterceptingFrameLayout.RegionInterceptableView; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.qs.SecureSetting; import com.android.systemui.tuner.TunerService; @@ -92,13 +93,12 @@ import java.util.ArrayList; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * An overlay that draws screen decorations in software (e.g for rounded corners or display cutout) * for antialiasing and emulation purposes. */ -@Singleton +@SysUISingleton public class ScreenDecorations extends SystemUI implements Tunable { private static final boolean DEBUG = false; private static final String TAG = "ScreenDecorations"; diff --git a/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java b/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java index 73295a3d8814..34efa35c37c5 100644 --- a/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java +++ b/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java @@ -41,6 +41,7 @@ import android.widget.LinearLayout; import android.widget.PopupWindow; import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.statusbar.CommandQueue; @@ -48,10 +49,9 @@ import com.android.systemui.statusbar.CommandQueue; import java.lang.ref.WeakReference; import javax.inject.Inject; -import javax.inject.Singleton; /** Shows a restart-activity button when the foreground activity is in size compatibility mode. */ -@Singleton +@SysUISingleton public class SizeCompatModeActivityController extends SystemUI implements CommandQueue.Callbacks { private static final String TAG = "SizeCompatMode"; diff --git a/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java b/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java index 7a4ef2b7bbf2..0b997d0e0955 100644 --- a/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java +++ b/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java @@ -29,15 +29,15 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.settingslib.SliceBroadcastRelay; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import javax.inject.Inject; -import javax.inject.Singleton; /** * Allows settings to register certain broadcasts to launch the settings app for pinned slices. * @see SliceBroadcastRelay */ -@Singleton +@SysUISingleton public class SliceBroadcastRelayHandler extends SystemUI { private static final String TAG = "SliceBroadcastRelay"; private static final boolean DEBUG = false; diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java index 627f5592e667..bb7906e7c3ae 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java @@ -29,7 +29,7 @@ import androidx.annotation.Nullable; import androidx.core.app.AppComponentFactory; import com.android.systemui.dagger.ContextComponentHelper; -import com.android.systemui.dagger.GlobalRootComponent; +import com.android.systemui.dagger.SysUIComponent; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -65,7 +65,7 @@ public class SystemUIAppComponentFactory extends AppComponentFactory { ((ContextInitializer) app).setContextAvailableCallback( context -> { SystemUIFactory.createFromConfig(context); - SystemUIFactory.getInstance().getRootComponent().inject( + SystemUIFactory.getInstance().getSysUIComponent().inject( SystemUIAppComponentFactory.this); } ); @@ -85,8 +85,8 @@ public class SystemUIAppComponentFactory extends AppComponentFactory { ((ContextInitializer) contentProvider).setContextAvailableCallback( context -> { SystemUIFactory.createFromConfig(context); - GlobalRootComponent rootComponent = - SystemUIFactory.getInstance().getRootComponent(); + SysUIComponent rootComponent = + SystemUIFactory.getInstance().getSysUIComponent(); try { Method injectMethod = rootComponent.getClass() .getMethod("inject", contentProvider.getClass()); @@ -111,7 +111,7 @@ public class SystemUIAppComponentFactory extends AppComponentFactory { if (mComponentHelper == null) { // This shouldn't happen, but is seen on occasion. // Bug filed against framework to take a look: http://b/141008541 - SystemUIFactory.getInstance().getRootComponent().inject( + SystemUIFactory.getInstance().getSysUIComponent().inject( SystemUIAppComponentFactory.this); } Activity activity = mComponentHelper.resolveActivity(className); @@ -129,7 +129,7 @@ public class SystemUIAppComponentFactory extends AppComponentFactory { if (mComponentHelper == null) { // This shouldn't happen, but does when a device is freshly formatted. // Bug filed against framework to take a look: http://b/141008541 - SystemUIFactory.getInstance().getRootComponent().inject( + SystemUIFactory.getInstance().getSysUIComponent().inject( SystemUIAppComponentFactory.this); } Service service = mComponentHelper.resolveService(className); @@ -147,7 +147,7 @@ public class SystemUIAppComponentFactory extends AppComponentFactory { if (mComponentHelper == null) { // This shouldn't happen, but does when a device is freshly formatted. // Bug filed against framework to take a look: http://b/141008541 - SystemUIFactory.getInstance().getRootComponent().inject( + SystemUIFactory.getInstance().getSysUIComponent().inject( SystemUIAppComponentFactory.this); } BroadcastReceiver receiver = mComponentHelper.resolveBroadcastReceiver(className); diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java index 4f78f65f0121..7dcec3d75367 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java @@ -33,6 +33,7 @@ import android.util.TimingsTraceLog; import com.android.systemui.dagger.ContextComponentHelper; import com.android.systemui.dagger.GlobalRootComponent; +import com.android.systemui.dagger.SysUIComponent; import com.android.systemui.dump.DumpManager; import com.android.systemui.util.NotificationChannels; @@ -58,6 +59,7 @@ public class SystemUIApplication extends Application implements private boolean mServicesStarted; private SystemUIAppComponentFactory.ContextAvailableCallback mContextAvailableCallback; private GlobalRootComponent mRootComponent; + private SysUIComponent mSysUIComponent; public SystemUIApplication() { super(); @@ -75,8 +77,9 @@ public class SystemUIApplication extends Application implements log.traceBegin("DependencyInjection"); mContextAvailableCallback.onContextAvailable(this); mRootComponent = SystemUIFactory.getInstance().getRootComponent(); - mComponentHelper = mRootComponent.getContextComponentHelper(); - mBootCompleteCache = mRootComponent.provideBootCacheImpl(); + mSysUIComponent = SystemUIFactory.getInstance().getSysUIComponent(); + mComponentHelper = mSysUIComponent.getContextComponentHelper(); + mBootCompleteCache = mSysUIComponent.provideBootCacheImpl(); log.traceEnd(); // Set the application theme that is inherited by all services. Note that setting the @@ -172,7 +175,7 @@ public class SystemUIApplication extends Application implements } } - final DumpManager dumpManager = mRootComponent.createDumpManager(); + final DumpManager dumpManager = mSysUIComponent.createDumpManager(); Log.v(TAG, "Starting SystemUI services for user " + Process.myUserHandle().getIdentifier() + "."); @@ -215,7 +218,7 @@ public class SystemUIApplication extends Application implements dumpManager.registerDumpable(mServices[i].getClass().getName(), mServices[i]); } - mRootComponent.getInitController().executePostInitTasks(); + mSysUIComponent.getInitController().executePostInitTasks(); log.traceEnd(); mServicesStarted = true; @@ -224,7 +227,7 @@ public class SystemUIApplication extends Application implements @Override public void onConfigurationChanged(Configuration newConfig) { if (mServicesStarted) { - mRootComponent.getConfigurationController().onConfigurationChanged(newConfig); + mSysUIComponent.getConfigurationController().onConfigurationChanged(newConfig); int len = mServices.length; for (int i = 0; i < len; i++) { if (mServices[i] != null) { diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index d987ad3b218d..f5c364947a2f 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -27,23 +27,15 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.ViewMediatorCallback; -import com.android.systemui.bubbles.BubbleController; import com.android.systemui.dagger.DaggerGlobalRootComponent; import com.android.systemui.dagger.GlobalRootComponent; import com.android.systemui.dagger.SysUIComponent; import com.android.systemui.dagger.WMComponent; import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.plugins.FalsingManager; -import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider; -import com.android.systemui.statusbar.NotificationListener; -import com.android.systemui.statusbar.NotificationMediaManager; -import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; -import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBouncer; import com.android.systemui.statusbar.phone.KeyguardBypassController; -import com.android.systemui.statusbar.phone.NotificationIconAreaController; -import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.KeyguardStateController; import java.util.concurrent.Executor; @@ -99,7 +91,7 @@ public class SystemUIFactory { // Every other part of our codebase currently relies on Dependency, so we // really need to ensure the Dependency gets initialized early on. - Dependency dependency = mRootComponent.createDependency(); + Dependency dependency = mSysUIComponent.createDependency(); dependency.start(); } @@ -113,6 +105,10 @@ public class SystemUIFactory { return mRootComponent; } + public SysUIComponent getSysUIComponent() { + return mSysUIComponent; + } + /** Returns the list of system UI components that should be started. */ public String[] getSystemUIServiceComponents(Resources resources) { return resources.getStringArray(R.array.config_systemUIServiceComponents); @@ -146,17 +142,4 @@ public class SystemUIFactory { Dependency.get(KeyguardUpdateMonitor.class), bypassController, new Handler(Looper.getMainLooper())); } - - public NotificationIconAreaController createNotificationIconAreaController(Context context, - StatusBar statusBar, - NotificationWakeUpCoordinator wakeUpCoordinator, - KeyguardBypassController keyguardBypassController, - StatusBarStateController statusBarStateController) { - return new NotificationIconAreaController(context, statusBar, statusBarStateController, - wakeUpCoordinator, keyguardBypassController, - Dependency.get(NotificationMediaManager.class), - Dependency.get(NotificationListener.class), - Dependency.get(DozeParameters.class), - Dependency.get(BubbleController.class)); - } } diff --git a/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java b/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java index d5a46de980f9..e26dc7f0545e 100644 --- a/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java +++ b/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java @@ -16,18 +16,19 @@ package com.android.systemui; +import com.android.systemui.dagger.SysUISingleton; + import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import javax.inject.Inject; -import javax.inject.Singleton; /** * Thread that offloads work from the UI thread but that is still perceptible to the user, so the * priority is the same as the main thread. */ -@Singleton +@SysUISingleton public class UiOffloadThread { private final ExecutorService mExecutorService = Executors.newSingleThreadExecutor(); diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java b/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java index fe07ab67c707..123d678fb185 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java @@ -22,8 +22,7 @@ import android.hardware.display.DisplayManager; import android.view.Display; import com.android.internal.annotations.VisibleForTesting; - -import javax.inject.Singleton; +import com.android.systemui.dagger.SysUISingleton; /** * A class to control {@link MagnificationModeSwitch}. It should show the button UI with following @@ -33,7 +32,7 @@ import javax.inject.Singleton; * <li> The magnification scale is changed by a user.</li> * <ol> */ -@Singleton +@SysUISingleton public class ModeSwitchesController { private final DisplayIdIndexSupplier<MagnificationModeSwitch> mSwitchSupplier; diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java index 17525798ae08..e49a5be58cfc 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java @@ -51,18 +51,18 @@ import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActiv import com.android.internal.util.ScreenshotHelper; import com.android.systemui.Dependency; import com.android.systemui.SystemUI; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.recents.Recents; import com.android.systemui.statusbar.phone.StatusBar; import java.util.Locale; import javax.inject.Inject; -import javax.inject.Singleton; /** * Class to register system actions with accessibility framework. */ -@Singleton +@SysUISingleton public class SystemActions extends SystemUI { private static final String TAG = "SystemActions"; diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java index d5f74a86fd94..f601c52ba98e 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java @@ -33,11 +33,11 @@ import android.view.accessibility.IWindowMagnificationConnectionCallback; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.systemui.SystemUI; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.CommandQueue; import javax.inject.Inject; -import javax.inject.Singleton; /** * Class to handle the interaction with @@ -45,7 +45,7 @@ import javax.inject.Singleton; * {@link AccessibilityManager#setWindowMagnificationConnection(IWindowMagnificationConnection)} * when {@code IStatusBar#requestWindowMagnificationConnection(boolean)} is called. */ -@Singleton +@SysUISingleton public class WindowMagnification extends SystemUI implements WindowMagnifierCallback, CommandQueue.Callbacks { private static final String TAG = "WindowMagnification"; diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java index 8187a2235c0a..eeb3b28357d7 100644 --- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java @@ -33,6 +33,7 @@ import androidx.annotation.WorkerThread; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dump.DumpManager; import com.android.systemui.util.Assert; @@ -44,7 +45,6 @@ import java.util.List; import java.util.Set; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controller to keep track of applications that have requested access to given App Ops @@ -52,7 +52,7 @@ import javax.inject.Singleton; * It can be subscribed to with callbacks. Additionally, it passes on the information to * NotificationPresenter to be displayed to the user. */ -@Singleton +@SysUISingleton public class AppOpsControllerImpl implements AppOpsController, AppOpsManager.OnOpActiveChangedInternalListener, AppOpsManager.OnOpNotedListener, Dumpable { diff --git a/packages/SystemUI/src/com/android/systemui/appops/PermissionFlagsCache.kt b/packages/SystemUI/src/com/android/systemui/appops/PermissionFlagsCache.kt index 45ed78f750be..3fd838be781d 100644 --- a/packages/SystemUI/src/com/android/systemui/appops/PermissionFlagsCache.kt +++ b/packages/SystemUI/src/com/android/systemui/appops/PermissionFlagsCache.kt @@ -19,11 +19,11 @@ package com.android.systemui.appops import android.content.pm.PackageManager import android.os.UserHandle import androidx.annotation.WorkerThread +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.util.Assert import java.util.concurrent.Executor import javax.inject.Inject -import javax.inject.Singleton private data class PermissionFlagKey( val permission: String, @@ -37,7 +37,7 @@ private data class PermissionFlagKey( * After a specific `{permission, package, uid}` has been requested, updates to it will be tracked, * and changes to the uid will trigger new requests (in the background). */ -@Singleton +@SysUISingleton class PermissionFlagsCache @Inject constructor( private val packageManager: PackageManager, @Background private val executor: Executor diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java index 2df48fc90a94..4390d513a9fb 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java @@ -33,9 +33,10 @@ import com.android.internal.app.AssistUtils; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; -import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.navigationbar.NavigationModeController; +import com.android.systemui.shared.system.QuickStepContract; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -45,7 +46,6 @@ import java.util.concurrent.TimeUnit; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Provider; -import javax.inject.Singleton; import dagger.Lazy; @@ -55,7 +55,7 @@ import dagger.Lazy; * Controls when visual handles for Assistant gesture affordance should be shown or hidden using an * {@link AssistHandleBehavior}. */ -@Singleton +@SysUISingleton public final class AssistHandleBehaviorController implements AssistHandleCallbacks, Dumpable { private static final String TAG = "AssistHandleBehavior"; diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java index ccca447ad842..5d8ec4bb330b 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java @@ -21,6 +21,7 @@ import android.content.Context; import androidx.annotation.Nullable; import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -29,7 +30,6 @@ import com.android.systemui.shared.system.QuickStepContract; import java.io.PrintWriter; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; @@ -37,7 +37,7 @@ import dagger.Lazy; * Assistant Handle behavior that makes Assistant handles show/hide when the home handle is * shown/hidden, respectively. */ -@Singleton +@SysUISingleton final class AssistHandleLikeHomeBehavior implements BehaviorController { private final StatusBarStateController.StateListener mStatusBarStateListener = diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java index df913f9ce9cd..86d3254dc7f9 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java @@ -19,12 +19,12 @@ package com.android.systemui.assist; import android.content.Context; import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController; +import com.android.systemui.dagger.SysUISingleton; import javax.inject.Inject; -import javax.inject.Singleton; /** Assistant handle behavior that hides the Assistant handles. */ -@Singleton +@SysUISingleton final class AssistHandleOffBehavior implements BehaviorController { @Inject diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java index 8e49d584788a..1b2e4c6a595e 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java @@ -36,6 +36,7 @@ import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.systemui.BootCompleteCache; import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -54,7 +55,6 @@ import java.util.concurrent.TimeUnit; import javax.inject.Inject; import javax.inject.Named; -import javax.inject.Singleton; import dagger.Lazy; @@ -63,7 +63,7 @@ import dagger.Lazy; * shows the handles when on lockscreen, and shows the handles temporarily when changing tasks or * entering overview. */ -@Singleton +@SysUISingleton final class AssistHandleReminderExpBehavior implements BehaviorController { private static final String LEARNING_TIME_ELAPSED_KEY = "reminder_exp_learning_time_elapsed"; diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt b/packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt index 08edad3a7f7f..4d0fd4313209 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt @@ -28,11 +28,11 @@ import com.android.internal.util.FrameworkStatsLog import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.assist.AssistantInvocationEvent.Companion.deviceStateFromLegacyDeviceState import com.android.systemui.assist.AssistantInvocationEvent.Companion.eventFromLegacyInvocationType +import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject -import javax.inject.Singleton /** Class for reporting events related to Assistant sessions. */ -@Singleton +@SysUISingleton open class AssistLogger @Inject constructor( protected val context: Context, protected val uiEventLogger: UiEventLogger, diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java index 6d179f27f4fb..e85cafaf47ac 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java @@ -46,6 +46,7 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.settingslib.applications.InterestingConfigChanges; import com.android.systemui.R; import com.android.systemui.assist.ui.DefaultUiController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.model.SysUiState; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.statusbar.CommandQueue; @@ -53,14 +54,13 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; /** * Class to manage everything related to assist in SystemUI. */ -@Singleton +@SysUISingleton public class AssistManager { /** diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java b/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java index 0dc06f2d5e21..ef43f87d20e8 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java @@ -25,13 +25,13 @@ import androidx.annotation.Nullable; import androidx.slice.Clock; import com.android.internal.app.AssistUtils; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.navigationbar.NavigationBarController; import java.util.EnumMap; import java.util.Map; import javax.inject.Named; -import javax.inject.Singleton; import dagger.Module; import dagger.Provides; @@ -44,7 +44,7 @@ public abstract class AssistModule { static final String UPTIME_NAME = "uptime"; @Provides - @Singleton + @SysUISingleton @Named(ASSIST_HANDLE_THREAD_NAME) static Handler provideBackgroundHandler() { final HandlerThread backgroundHandlerThread = @@ -54,7 +54,7 @@ public abstract class AssistModule { } @Provides - @Singleton + @SysUISingleton static Map<AssistHandleBehavior, AssistHandleBehaviorController.BehaviorController> provideAssistHandleBehaviorControllerMap( AssistHandleOffBehavior offBehavior, @@ -76,13 +76,13 @@ public abstract class AssistModule { } @Provides - @Singleton + @SysUISingleton static AssistUtils provideAssistUtils(Context context) { return new AssistUtils(context); } @Provides - @Singleton + @SysUISingleton @Named(UPTIME_NAME) static Clock provideSystemClock() { return SystemClock::uptimeMillis; diff --git a/packages/SystemUI/src/com/android/systemui/assist/DeviceConfigHelper.java b/packages/SystemUI/src/com/android/systemui/assist/DeviceConfigHelper.java index 86b7c748ea77..4d5c44c9e88d 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/DeviceConfigHelper.java +++ b/packages/SystemUI/src/com/android/systemui/assist/DeviceConfigHelper.java @@ -22,17 +22,18 @@ import android.provider.DeviceConfig; import androidx.annotation.Nullable; +import com.android.systemui.dagger.SysUISingleton; + import java.util.concurrent.Executor; import javax.inject.Inject; -import javax.inject.Singleton; /** * Wrapper class for retrieving System UI device configuration values. * * Can be mocked in tests for ease of testing the effects of particular values. */ -@Singleton +@SysUISingleton public class DeviceConfigHelper { @Inject diff --git a/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java b/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java index 257ad50eff61..50d559b7aeab 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java @@ -30,6 +30,7 @@ import androidx.annotation.Nullable; import com.android.systemui.BootCompleteCache; import com.android.systemui.Dependency; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.PackageManagerWrapper; @@ -42,12 +43,11 @@ import java.util.List; import java.util.Optional; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; /** Class to monitor and report the state of the phone. */ -@Singleton +@SysUISingleton public final class PhoneStateMonitor { public static final int PHONE_STATE_AOD1 = 1; diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java index 722e3124d871..1d9009668b47 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java +++ b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java @@ -41,18 +41,18 @@ import com.android.systemui.assist.AssistHandleViewController; import com.android.systemui.assist.AssistLogger; import com.android.systemui.assist.AssistManager; import com.android.systemui.assist.AssistantSessionEvent; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.navigationbar.NavigationBarController; import java.util.Locale; import javax.inject.Inject; -import javax.inject.Singleton; /** * Default UiController implementation. Shows white edge lights along the bottom of the phone, * expanding from the corners to meet in the center. */ -@Singleton +@SysUISingleton public class DefaultUiController implements AssistManager.UiController { private static final String TAG = "DefaultUiController"; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index ade106fb2223..ea18b11413ef 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -49,25 +49,28 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.SomeArgs; import com.android.systemui.SystemUI; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.doze.DozeReceiver; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * Receives messages sent from {@link com.android.server.biometrics.BiometricService} and shows the * appropriate biometric UI (e.g. BiometricDialogView). */ -@Singleton +@SysUISingleton public class AuthController extends SystemUI implements CommandQueue.Callbacks, - AuthDialogCallback { + AuthDialogCallback, DozeReceiver { - private static final String TAG = "BiometricPrompt/AuthController"; + private static final String TAG = "AuthController"; private static final boolean DEBUG = true; private final CommandQueue mCommandQueue; + private final StatusBarStateController mStatusBarStateController; private final Injector mInjector; // TODO: These should just be saved from onSaveState @@ -77,6 +80,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, private Handler mHandler = new Handler(Looper.getMainLooper()); private WindowManager mWindowManager; + @Nullable private UdfpsController mUdfpsController; @VisibleForTesting IActivityTaskManager mActivityTaskManager; @@ -143,6 +147,13 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, }; @Override + public void dozeTimeTick() { + if (mUdfpsController != null) { + mUdfpsController.dozeTimeTick(); + } + } + + @Override public void onTryAgainPressed() { if (mReceiver == null) { Log.e(TAG, "onTryAgainPressed: Receiver is null"); @@ -251,14 +262,17 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, } @Inject - public AuthController(Context context, CommandQueue commandQueue) { - this(context, commandQueue, new Injector()); + public AuthController(Context context, CommandQueue commandQueue, + StatusBarStateController statusBarStateController) { + this(context, commandQueue, statusBarStateController, new Injector()); } @VisibleForTesting - AuthController(Context context, CommandQueue commandQueue, Injector injector) { + AuthController(Context context, CommandQueue commandQueue, + StatusBarStateController statusBarStateController, Injector injector) { super(context); mCommandQueue = commandQueue; + mStatusBarStateController = statusBarStateController; mInjector = injector; IntentFilter filter = new IntentFilter(); @@ -280,7 +294,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, fpm.getSensorProperties(); for (FingerprintSensorProperties props : fingerprintSensorProperties) { if (props.sensorType == FingerprintSensorProperties.TYPE_UDFPS) { - mUdfpsController = new UdfpsController(mContext); + mUdfpsController = new UdfpsController(mContext, mStatusBarStateController); break; } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index e3126b89fe78..82fb80892ab1 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -16,6 +16,7 @@ package com.android.systemui.biometrics; +import android.annotation.NonNull; import android.annotation.SuppressLint; import android.content.ContentResolver; import android.content.Context; @@ -29,16 +30,18 @@ import android.os.Looper; import android.os.PowerManager; import android.os.UserHandle; import android.provider.Settings; +import android.text.TextUtils; import android.util.Log; import android.util.MathUtils; import android.util.Spline; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.WindowManager; -import android.widget.LinearLayout; import com.android.internal.BrightnessSynchronizer; import com.android.systemui.R; +import com.android.systemui.doze.DozeReceiver; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import java.io.FileWriter; import java.io.IOException; @@ -47,7 +50,7 @@ import java.io.IOException; * Shows and hides the under-display fingerprint sensor (UDFPS) overlay, handles UDFPS touch events, * and coordinates triggering of the high-brightness mode (HBM). */ -class UdfpsController { +class UdfpsController implements DozeReceiver { private static final String TAG = "UdfpsController"; // Gamma approximation for the sRGB color space. private static final float DISPLAY_GAMMA = 2.2f; @@ -56,12 +59,13 @@ class UdfpsController { private final WindowManager mWindowManager; private final ContentResolver mContentResolver; private final Handler mHandler; - private final UdfpsView mView; private final WindowManager.LayoutParams mLayoutParams; + private final UdfpsView mView; // Debugfs path to control the high-brightness mode. private final String mHbmPath; private final String mHbmEnableCommand; private final String mHbmDisableCommand; + private final boolean mHbmSupported; // Brightness in nits in the high-brightness mode. private final float mHbmNits; // A spline mapping from the device's backlight value, normalized to the range [0, 1.0], to a @@ -86,27 +90,33 @@ class UdfpsController { public void hideUdfpsOverlay() { UdfpsController.this.hideUdfpsOverlay(); } + + @Override + public void setDebugMessage(String message) { + mView.setDebugMessage(message); + } } @SuppressLint("ClickableViewAccessibility") private final UdfpsView.OnTouchListener mOnTouchListener = (v, event) -> { UdfpsView view = (UdfpsView) v; + final boolean isFingerDown = view.isScrimShowing(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: - boolean isValidTouch = view.isValidTouch(event.getX(), event.getY(), + final boolean isValidTouch = view.isValidTouch(event.getX(), event.getY(), event.getPressure()); - if (!view.isFingerDown() && isValidTouch) { + if (!isFingerDown && isValidTouch) { onFingerDown((int) event.getX(), (int) event.getY(), event.getTouchMinor(), event.getTouchMajor()); - } else if (view.isFingerDown() && !isValidTouch) { + } else if (isFingerDown && !isValidTouch) { onFingerUp(); } return true; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: - if (view.isFingerDown()) { + if (isFingerDown) { onFingerUp(); } return true; @@ -116,23 +126,24 @@ class UdfpsController { } }; - UdfpsController(Context context) { + UdfpsController(@NonNull Context context, + @NonNull StatusBarStateController statusBarStateController) { mFingerprintManager = context.getSystemService(FingerprintManager.class); mWindowManager = context.getSystemService(WindowManager.class); mContentResolver = context.getContentResolver(); mHandler = new Handler(Looper.getMainLooper()); - mLayoutParams = createLayoutParams(context); - LinearLayout layout = new LinearLayout(context); - layout.setLayoutParams(mLayoutParams); - mView = (UdfpsView) LayoutInflater.from(context).inflate(R.layout.udfps_view, layout, - false); - mView.setOnTouchListener(mOnTouchListener); + + mView = (UdfpsView) LayoutInflater.from(context).inflate(R.layout.udfps_view, null, false); mHbmPath = context.getResources().getString(R.string.udfps_hbm_sysfs_path); mHbmEnableCommand = context.getResources().getString(R.string.udfps_hbm_enable_command); mHbmDisableCommand = context.getResources().getString(R.string.udfps_hbm_disable_command); + mHbmSupported = !TextUtils.isEmpty(mHbmPath); + mView.setHbmSupported(mHbmSupported); + statusBarStateController.addCallback(mView); + // This range only consists of the minimum and maximum values, which only cover // non-high-brightness mode. float[] nitsRange = toFloatArray(context.getResources().obtainTypedArray( @@ -166,27 +177,39 @@ class UdfpsController { mIsOverlayShowing = false; } + @Override + public void dozeTimeTick() { + mView.dozeTimeTick(); + } + private void showUdfpsOverlay() { mHandler.post(() -> { - Log.v(TAG, "showUdfpsOverlay | adding window"); if (!mIsOverlayShowing) { try { + Log.v(TAG, "showUdfpsOverlay | adding window"); mWindowManager.addView(mView, mLayoutParams); mIsOverlayShowing = true; + mView.setOnTouchListener(mOnTouchListener); } catch (RuntimeException e) { Log.e(TAG, "showUdfpsOverlay | failed to add window", e); } + } else { + Log.v(TAG, "showUdfpsOverlay | the overlay is already showing"); } }); } private void hideUdfpsOverlay() { - onFingerUp(); mHandler.post(() -> { - Log.v(TAG, "hideUdfpsOverlay | removing window"); if (mIsOverlayShowing) { + Log.v(TAG, "hideUdfpsOverlay | removing window"); + mView.setOnTouchListener(null); + // Reset the controller back to its starting state. + onFingerUp(); mWindowManager.removeView(mView); mIsOverlayShowing = false; + } else { + Log.v(TAG, "hideUdfpsOverlay | the overlay is already hidden"); } }); } @@ -219,26 +242,33 @@ class UdfpsController { private void onFingerDown(int x, int y, float minor, float major) { mView.setScrimAlpha(computeScrimOpacity()); + mView.showScrimAndDot(); try { - FileWriter fw = new FileWriter(mHbmPath); - fw.write(mHbmEnableCommand); - fw.close(); + if (mHbmSupported) { + FileWriter fw = new FileWriter(mHbmPath); + fw.write(mHbmEnableCommand); + fw.close(); + } + mFingerprintManager.onFingerDown(x, y, minor, major); } catch (IOException e) { + mView.hideScrimAndDot(); Log.e(TAG, "onFingerDown | failed to enable HBM: " + e.getMessage()); } - mView.onFingerDown(); - mFingerprintManager.onFingerDown(x, y, minor, major); } private void onFingerUp() { mFingerprintManager.onFingerUp(); - mView.onFingerUp(); - try { - FileWriter fw = new FileWriter(mHbmPath); - fw.write(mHbmDisableCommand); - fw.close(); - } catch (IOException e) { - Log.e(TAG, "onFingerUp | failed to disable HBM: " + e.getMessage()); + // Hiding the scrim before disabling HBM results in less noticeable flicker. + mView.hideScrimAndDot(); + if (mHbmSupported) { + try { + FileWriter fw = new FileWriter(mHbmPath); + fw.write(mHbmDisableCommand); + fw.close(); + } catch (IOException e) { + mView.showScrimAndDot(); + Log.e(TAG, "onFingerUp | failed to disable HBM: " + e.getMessage()); + } } } @@ -254,11 +284,12 @@ class UdfpsController { // TODO(b/152419866): Use the UDFPS window type when it becomes available. WindowManager.LayoutParams.TYPE_BOOT_PROGRESS, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, PixelFormat.TRANSLUCENT); lp.setTitle(TAG); - lp.windowAnimations = 0; + lp.setFitInsetsTypes(0); return lp; } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java index d4e86d5dd234..36353fa96956 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java @@ -16,6 +16,8 @@ package com.android.systemui.biometrics; +import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset; + import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; @@ -23,21 +25,33 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; +import android.util.MathUtils; import android.view.View; import android.view.ViewTreeObserver; import com.android.systemui.R; +import com.android.systemui.doze.DozeReceiver; +import com.android.systemui.plugins.statusbar.StatusBarStateController; /** * A full screen view with a configurable illumination dot and scrim. */ -public class UdfpsView extends View { +public class UdfpsView extends View implements DozeReceiver, + StatusBarStateController.StateListener { private static final String TAG = "UdfpsView"; + // Values in pixels. + private static final float SENSOR_SHADOW_RADIUS = 2.0f; + private static final float SENSOR_OUTLINE_WIDTH = 2.0f; + + private static final int DEBUG_TEXT_SIZE_PX = 32; + private final Rect mScrimRect; private final Paint mScrimPaint; + private final Paint mDebugTextPaint; private float mSensorX; private float mSensorY; @@ -46,11 +60,20 @@ public class UdfpsView extends View { private final float mSensorRadius; private final float mSensorMarginBottom; private final float mSensorTouchAreaCoefficient; + private final int mMaxBurnInOffsetX; + private final int mMaxBurnInOffsetY; private final Rect mTouchableRegion; private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener; - private boolean mIsFingerDown; + // AOD anti-burn-in offsets + private float mInterpolatedDarkAmount; + private float mBurnInOffsetX; + private float mBurnInOffsetY; + + private boolean mIsScrimShowing; + private boolean mHbmSupported; + private String mDebugMessage; public UdfpsView(Context context, AttributeSet attrs) { super(context, attrs); @@ -76,6 +99,10 @@ public class UdfpsView extends View { a.recycle(); } + mMaxBurnInOffsetX = getResources() + .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_x); + mMaxBurnInOffsetY = getResources() + .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y); mScrimRect = new Rect(); mScrimPaint = new Paint(0 /* flags */); @@ -83,8 +110,17 @@ public class UdfpsView extends View { mSensorRect = new RectF(); mSensorPaint = new Paint(0 /* flags */); + mSensorPaint.setAntiAlias(true); mSensorPaint.setColor(Color.WHITE); mSensorPaint.setStyle(Paint.Style.STROKE); + mSensorPaint.setStrokeWidth(SENSOR_OUTLINE_WIDTH); + mSensorPaint.setShadowLayer(SENSOR_SHADOW_RADIUS, 0, 0, Color.BLACK); + mSensorPaint.setAntiAlias(true); + + mDebugTextPaint = new Paint(); + mDebugTextPaint.setAntiAlias(true); + mDebugTextPaint.setColor(Color.BLUE); + mDebugTextPaint.setTextSize(DEBUG_TEXT_SIZE_PX); mTouchableRegion = new Rect(); mInsetsListener = internalInsetsInfo -> { @@ -93,7 +129,30 @@ public class UdfpsView extends View { internalInsetsInfo.touchableRegion.set(mTouchableRegion); }; - mIsFingerDown = false; + mIsScrimShowing = false; + } + + @Override + public void dozeTimeTick() { + updateAodPosition(); + } + + @Override + public void onDozeAmountChanged(float linear, float eased) { + mInterpolatedDarkAmount = eased; + updateAodPosition(); + } + + private void updateAodPosition() { + mBurnInOffsetX = MathUtils.lerp(0f, + getBurnInOffset(mMaxBurnInOffsetX * 2, true /* xAxis */) + - mMaxBurnInOffsetX, + mInterpolatedDarkAmount); + mBurnInOffsetY = MathUtils.lerp(0f, + getBurnInOffset(mMaxBurnInOffsetY * 2, false /* xAxis */) + - 0.5f * mMaxBurnInOffsetY, + mInterpolatedDarkAmount); + postInvalidate(); } @Override @@ -108,6 +167,8 @@ public class UdfpsView extends View { mSensorY = h - mSensorMarginBottom - mSensorRadius; mSensorRect.set(mSensorX - mSensorRadius, mSensorY - mSensorRadius, mSensorX + mSensorRadius, mSensorY + mSensorRadius); + + // Sets mTouchableRegion with rounded up values from mSensorRect. mSensorRect.roundOut(mTouchableRegion); getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsListener); @@ -123,10 +184,29 @@ public class UdfpsView extends View { @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); - if (mIsFingerDown) { + + if (mIsScrimShowing && mHbmSupported) { + // Only draw the scrim if HBM is supported. canvas.drawRect(mScrimRect, mScrimPaint); } + + // Translation should affect everything but the scrim. + canvas.save(); + canvas.translate(mBurnInOffsetX, mBurnInOffsetY); + if (!TextUtils.isEmpty(mDebugMessage)) { + canvas.drawText(mDebugMessage, 0, 160, mDebugTextPaint); + } canvas.drawOval(mSensorRect, mSensorPaint); + canvas.restore(); + } + + void setHbmSupported(boolean hbmSupported) { + mHbmSupported = hbmSupported; + } + + void setDebugMessage(String message) { + mDebugMessage = message; + postInvalidate(); } boolean isValidTouch(float x, float y, float pressure) { @@ -140,19 +220,19 @@ public class UdfpsView extends View { mScrimPaint.setAlpha(alpha); } - boolean isFingerDown() { - return mIsFingerDown; + boolean isScrimShowing() { + return mIsScrimShowing; } - void onFingerDown() { - mIsFingerDown = true; + void showScrimAndDot() { + mIsScrimShowing = true; mSensorPaint.setStyle(Paint.Style.FILL); - postInvalidate(); + invalidate(); } - void onFingerUp() { - mIsFingerDown = false; + void hideScrimAndDot() { + mIsScrimShowing = false; mSensorPaint.setStyle(Paint.Style.STROKE); - postInvalidate(); + invalidate(); } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index 9c5f9fe8bcc0..9e9d85a7cd1c 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -84,7 +84,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.Dumpable; -import com.android.systemui.bubbles.animation.StackAnimationController; import com.android.systemui.bubbles.dagger.BubbleModule; import com.android.systemui.dump.DumpManager; import com.android.systemui.model.SysUiState; @@ -96,6 +95,7 @@ import com.android.systemui.shared.system.WindowManagerWrapper; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationRemoveInterceptor; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.ScrimView; import com.android.systemui.statusbar.notification.NotificationChannelHelper; import com.android.systemui.statusbar.notification.NotificationEntryListener; @@ -109,7 +109,6 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.No import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.phone.NotificationGroupManager; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java index 10f4385ed443..5c6d16d4bbee 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java @@ -34,7 +34,7 @@ import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.R; import com.android.systemui.bubbles.BubbleController.DismissReason; -import com.android.systemui.shared.system.SysUiStatsLog; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -52,12 +52,11 @@ import java.util.function.Consumer; import java.util.function.Predicate; import javax.inject.Inject; -import javax.inject.Singleton; /** * Keeps track of active bubbles. */ -@Singleton +@SysUISingleton public class BubbleData { private BubbleLoggerImpl mLogger = new BubbleLoggerImpl(); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt index db64a13f3df3..f129d3147032 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt @@ -18,25 +18,24 @@ package com.android.systemui.bubbles import android.annotation.SuppressLint import android.annotation.UserIdInt import android.content.pm.LauncherApps +import android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_CACHED import android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC import android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER -import android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_CACHED import android.os.UserHandle import android.util.Log import com.android.systemui.bubbles.storage.BubbleEntity import com.android.systemui.bubbles.storage.BubblePersistentRepository import com.android.systemui.bubbles.storage.BubbleVolatileRepository +import com.android.systemui.dagger.SysUISingleton import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.launch import kotlinx.coroutines.yield - import javax.inject.Inject -import javax.inject.Singleton -@Singleton +@SysUISingleton internal class BubbleDataRepository @Inject constructor( private val volatileRepository: BubbleVolatileRepository, private val persistentRepository: BubblePersistentRepository, diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java index 10d301d0fa93..eecc41c697b3 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java @@ -25,23 +25,22 @@ import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.bubbles.BubbleData; import com.android.systemui.bubbles.BubbleDataRepository; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; 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.NotificationShadeWindowController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.phone.NotificationGroupManager; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.util.FloatingContentCoordinator; -import javax.inject.Singleton; - import dagger.Module; import dagger.Provides; @@ -51,7 +50,7 @@ public interface BubbleModule { /** */ - @Singleton + @SysUISingleton @Provides static BubbleController newBubbleController( Context context, diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubblePersistentRepository.kt b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubblePersistentRepository.kt index 5b4d8c71e5c0..f4479653d12e 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubblePersistentRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubblePersistentRepository.kt @@ -18,13 +18,13 @@ package com.android.systemui.bubbles.storage import android.content.Context import android.util.AtomicFile import android.util.Log +import com.android.systemui.dagger.SysUISingleton import java.io.File import java.io.FileOutputStream import java.io.IOException import javax.inject.Inject -import javax.inject.Singleton -@Singleton +@SysUISingleton class BubblePersistentRepository @Inject constructor( context: Context ) { diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt index 894970f903ac..c6d57326357c 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt @@ -19,8 +19,8 @@ import android.content.pm.LauncherApps import android.os.UserHandle import com.android.internal.annotations.VisibleForTesting import com.android.systemui.bubbles.ShortcutKey +import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject -import javax.inject.Singleton private const val CAPACITY = 16 @@ -28,7 +28,7 @@ private const val CAPACITY = 16 * BubbleVolatileRepository holds the most updated snapshot of list of bubbles for in-memory * manipulation. */ -@Singleton +@SysUISingleton class BubbleVolatileRepository @Inject constructor( private val launcherApps: LauncherApps ) { diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java index f35322bd2a77..83b6df3e701b 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java @@ -31,6 +31,7 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.Dumpable; import com.android.systemui.classifier.brightline.BrightLineFalsingManager; import com.android.systemui.classifier.brightline.FalsingDataProvider; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.dock.DockManager; @@ -48,14 +49,13 @@ import java.io.PrintWriter; import java.util.concurrent.Executor; import javax.inject.Inject; -import javax.inject.Singleton; /** * Simple passthrough implementation of {@link FalsingManager} allowing plugins to swap in. * * {@link FalsingManagerImpl} is used when a Plugin is not loaded. */ -@Singleton +@SysUISingleton public class FalsingManagerProxy implements FalsingManager, Dumpable { private static final String PROXIMITY_SENSOR_TAG = "FalsingManager"; diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java index 3ca1f59fd793..5b33428ff5f1 100644 --- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java +++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java @@ -28,6 +28,7 @@ import com.android.internal.colorextraction.types.ExtractionType; import com.android.internal.colorextraction.types.Tonal; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.policy.ConfigurationController; import java.io.FileDescriptor; @@ -35,12 +36,11 @@ import java.io.PrintWriter; import java.util.Arrays; import javax.inject.Inject; -import javax.inject.Singleton; /** * ColorExtractor aware of wallpaper visibility */ -@Singleton +@SysUISingleton public class SysuiColorExtractor extends ColorExtractor implements Dumpable, ConfigurationController.ConfigurationListener { private static final String TAG = "SysuiColorExtractor"; diff --git a/packages/SystemUI/src/com/android/systemui/controls/CustomIconCache.kt b/packages/SystemUI/src/com/android/systemui/controls/CustomIconCache.kt index cca0f1653757..ed608499c601 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/CustomIconCache.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/CustomIconCache.kt @@ -19,8 +19,8 @@ package com.android.systemui.controls import android.content.ComponentName import android.graphics.drawable.Icon import androidx.annotation.GuardedBy +import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject -import javax.inject.Singleton /** * Icon cache for custom icons sent with controls. @@ -28,7 +28,7 @@ import javax.inject.Singleton * It assumes that only one component can be current at the time, to minimize the number of icons * stored at a given time. */ -@Singleton +@SysUISingleton class CustomIconCache @Inject constructor() { private var currentComponent: ComponentName? = null diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt index aa3e193ddba2..658f46e3bb96 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt @@ -28,14 +28,14 @@ import android.service.controls.IControlsSubscription import android.service.controls.actions.ControlAction import android.util.Log import com.android.internal.annotations.VisibleForTesting +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.util.concurrency.DelayableExecutor import dagger.Lazy import java.util.concurrent.atomic.AtomicBoolean import javax.inject.Inject -import javax.inject.Singleton -@Singleton +@SysUISingleton @VisibleForTesting open class ControlsBindingControllerImpl @Inject constructor( private val context: Context, diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt index 40c8c6bfa9f7..495872f3433d 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt @@ -42,6 +42,7 @@ import com.android.systemui.controls.ControlStatus import com.android.systemui.controls.ControlsServiceInfo import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.ui.ControlsUiController +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dump.DumpManager import com.android.systemui.globalactions.GlobalActionsDialog @@ -52,18 +53,17 @@ import java.util.Optional import java.util.concurrent.TimeUnit import java.util.function.Consumer import javax.inject.Inject -import javax.inject.Singleton -@Singleton +@SysUISingleton class ControlsControllerImpl @Inject constructor ( - private val context: Context, - @Background private val executor: DelayableExecutor, - private val uiController: ControlsUiController, - private val bindingController: ControlsBindingController, - private val listingController: ControlsListingController, - private val broadcastDispatcher: BroadcastDispatcher, - optionalWrapper: Optional<ControlsFavoritePersistenceWrapper>, - dumpManager: DumpManager + private val context: Context, + @Background private val executor: DelayableExecutor, + private val uiController: ControlsUiController, + private val bindingController: ControlsBindingController, + private val listingController: ControlsListingController, + private val broadcastDispatcher: BroadcastDispatcher, + optionalWrapper: Optional<ControlsFavoritePersistenceWrapper>, + dumpManager: DumpManager ) : Dumpable, ControlsController { companion object { diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt index 9a5b96078e95..38a82f8c9908 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt @@ -19,10 +19,10 @@ package com.android.systemui.controls.dagger import com.android.systemui.controls.controller.ControlsController import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.ui.ControlsUiController +import com.android.systemui.dagger.SysUISingleton import dagger.Lazy import java.util.Optional import javax.inject.Inject -import javax.inject.Singleton /** * Pseudo-component to inject into classes outside `com.android.systemui.controls`. @@ -30,7 +30,7 @@ import javax.inject.Singleton * If `featureEnabled` is false, all the optionals should be empty. The controllers will only be * instantiated if `featureEnabled` is true. */ -@Singleton +@SysUISingleton class ControlsComponent @Inject constructor( @ControlsFeatureEnabled private val featureEnabled: Boolean, private val lazyControlsController: Lazy<ControlsController>, diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt index 4760d291072e..fbdeb30d3911 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt @@ -33,13 +33,13 @@ import com.android.systemui.controls.ui.ControlActionCoordinator import com.android.systemui.controls.ui.ControlActionCoordinatorImpl import com.android.systemui.controls.ui.ControlsUiController import com.android.systemui.controls.ui.ControlsUiControllerImpl +import com.android.systemui.dagger.SysUISingleton import dagger.Binds import dagger.BindsOptionalOf import dagger.Module import dagger.Provides import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap -import javax.inject.Singleton /** * Module for injecting classes in `com.android.systemui.controls`- @@ -55,7 +55,7 @@ abstract class ControlsModule { companion object { @JvmStatic @Provides - @Singleton + @SysUISingleton @ControlsFeatureEnabled fun providesControlsFeatureEnabled(pm: PackageManager): Boolean { return pm.hasSystemFeature(PackageManager.FEATURE_CONTROLS) diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt index 1cd9712cd01b..0d4439fe8ccb 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt @@ -27,11 +27,11 @@ import com.android.internal.annotations.VisibleForTesting import com.android.settingslib.applications.ServiceListing import com.android.settingslib.widget.CandidateInfo import com.android.systemui.controls.ControlsServiceInfo +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import java.util.concurrent.Executor import java.util.concurrent.atomic.AtomicInteger import javax.inject.Inject -import javax.inject.Singleton private fun createServiceListing(context: Context): ServiceListing { return ServiceListing.Builder(context).apply { @@ -52,7 +52,7 @@ private fun createServiceListing(context: Context): ServiceListing { * * Has an intent-filter responding to [ControlsProviderService.CONTROLS_ACTION] * * Has the bind permission `android.permission.BIND_CONTROLS` */ -@Singleton +@SysUISingleton class ControlsListingControllerImpl @VisibleForTesting constructor( private val context: Context, @Background private val backgroundExecutor: Executor, diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt index e15380b42a78..ab8222547597 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt @@ -16,30 +16,29 @@ package com.android.systemui.controls.ui +import android.annotation.MainThread import android.app.Dialog import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.content.pm.ResolveInfo -import android.annotation.MainThread -import android.os.Vibrator import android.os.VibrationEffect +import android.os.Vibrator import android.service.controls.Control import android.service.controls.actions.BooleanAction import android.service.controls.actions.CommandAction import android.service.controls.actions.FloatAction import android.util.Log import android.view.HapticFeedbackConstants +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.globalactions.GlobalActionsComponent import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.concurrency.DelayableExecutor - import javax.inject.Inject -import javax.inject.Singleton -@Singleton +@SysUISingleton class ControlActionCoordinatorImpl @Inject constructor( private val context: Context, private val bgExecutor: DelayableExecutor, diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt index 5f75c96be128..371031020b14 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt @@ -52,6 +52,7 @@ import com.android.systemui.controls.management.ControlsEditingActivity import com.android.systemui.controls.management.ControlsFavoritingActivity import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.management.ControlsProviderSelectorActivity +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.globalactions.GlobalActionsPopupMenu @@ -62,11 +63,10 @@ import dagger.Lazy import java.text.Collator import java.util.function.Consumer import javax.inject.Inject -import javax.inject.Singleton private data class ControlKey(val componentName: ComponentName, val controlId: String) -@Singleton +@SysUISingleton class ControlsUiControllerImpl @Inject constructor ( val controlsController: Lazy<ControlsController>, val context: Context, diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java index f91d79576395..b41915bc2547 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java @@ -27,12 +27,11 @@ import java.util.Map; import javax.inject.Inject; import javax.inject.Provider; -import javax.inject.Singleton; /** * Used during Service and Activity instantiation to make them injectable. */ -@Singleton +@SysUISingleton public class ContextComponentResolver implements ContextComponentHelper { private final Map<Class<?>, Provider<Activity>> mActivityCreators; private final Map<Class<?>, Provider<Service>> mServiceCreators; diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java index 21bcfcd9fdaf..5a7772320139 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java @@ -51,6 +51,7 @@ import com.android.systemui.doze.AlwaysOnDisplayPolicy; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.model.SysUiState; +import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.plugins.PluginInitializerImpl; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -62,7 +63,6 @@ import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.DevicePolicyManagerWrapper; import com.android.systemui.stackdivider.Divider; import com.android.systemui.statusbar.CommandQueue; -import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.phone.AutoHideController; import com.android.systemui.statusbar.phone.ConfigurationControllerImpl; @@ -79,7 +79,6 @@ import java.util.Optional; import java.util.concurrent.Executor; import javax.inject.Named; -import javax.inject.Singleton; import dagger.Lazy; import dagger.Module; @@ -96,8 +95,9 @@ import dagger.Provides; @Module(includes = {NightDisplayListenerModule.class}) public class DependencyProvider { - @Singleton + /** */ @Provides + @SysUISingleton @Named(TIME_TICK_HANDLER_NAME) public Handler provideTimeTickHandler() { HandlerThread thread = new HandlerThread("TimeTick"); @@ -124,14 +124,16 @@ public class DependencyProvider { return new Handler(); } - @Singleton + /** */ @Provides + @SysUISingleton public DataSaverController provideDataSaverController(NetworkController networkController) { return networkController.getDataSaverController(); } - @Singleton + /** */ @Provides + @SysUISingleton public DisplayMetrics provideDisplayMetrics(Context context, WindowManager windowManager) { DisplayMetrics displayMetrics = new DisplayMetrics(); context.getDisplay().getMetrics(displayMetrics); @@ -139,41 +141,45 @@ public class DependencyProvider { } /** */ - @Singleton @Provides + @SysUISingleton public INotificationManager provideINotificationManager() { return INotificationManager.Stub.asInterface( ServiceManager.getService(Context.NOTIFICATION_SERVICE)); } /** */ - @Singleton @Provides + @SysUISingleton public LayoutInflater providerLayoutInflater(Context context) { return LayoutInflater.from(context); } - @Singleton + /** */ @Provides + @SysUISingleton public LeakDetector provideLeakDetector() { return LeakDetector.create(); } - @Singleton + /** */ @Provides + @SysUISingleton public MetricsLogger provideMetricsLogger() { return new MetricsLogger(); } - @Singleton + /** */ @Provides + @SysUISingleton public PluginManager providePluginManager(Context context) { return new PluginManagerImpl(context, new PluginInitializerImpl()); } - @Singleton + /** */ @Provides + @SysUISingleton public NavigationBarController provideNavigationBarController(Context context, WindowManager windowManager, Lazy<AssistManager> assistManagerLazy, @@ -220,29 +226,31 @@ public class DependencyProvider { configurationController); } - @Singleton + /** */ @Provides + @SysUISingleton public ConfigurationController provideConfigurationController(Context context) { return new ConfigurationControllerImpl(context); } /** */ - @Singleton + @SysUISingleton @Provides public AutoHideController provideAutoHideController(Context context, @Main Handler mainHandler, IWindowManager iWindowManager) { return new AutoHideController(context, mainHandler, iWindowManager); } - @Singleton + /** */ @Provides + @SysUISingleton public ActivityManagerWrapper provideActivityManagerWrapper() { return ActivityManagerWrapper.getInstance(); } /** Provides and initializes the {#link BroadcastDispatcher} for SystemUI */ - @Singleton @Provides + @SysUISingleton public BroadcastDispatcher providesBroadcastDispatcher( Context context, @Background Looper backgroundLooper, @@ -256,8 +264,9 @@ public class DependencyProvider { return bD; } - @Singleton + /** */ @Provides + @SysUISingleton public DevicePolicyManagerWrapper provideDevicePolicyManagerWrapper() { return DevicePolicyManagerWrapper.getInstance(); } @@ -293,22 +302,22 @@ public class DependencyProvider { } /** */ - @Singleton @Provides + @SysUISingleton public Choreographer providesChoreographer() { return Choreographer.getInstance(); } /** Provides an instance of {@link com.android.internal.logging.UiEventLogger} */ - @Singleton @Provides + @SysUISingleton static UiEventLogger provideUiEventLogger() { return new UiEventLoggerImpl(); } /** */ - @Singleton @Provides + @SysUISingleton public ModeSwitchesController providesModeSwitchesController(Context context) { return new ModeSwitchesController(context); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java b/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java new file mode 100644 index 000000000000..553655bf672c --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java @@ -0,0 +1,78 @@ +/* + * 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.dagger; + +import android.content.Context; +import android.content.SharedPreferences; +import android.hardware.display.AmbientDisplayConfiguration; +import android.util.DisplayMetrics; +import android.view.Choreographer; + +import com.android.systemui.Prefs; +import com.android.systemui.dagger.qualifiers.Main; + +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +/** + * Supplies globally scoped instances. + * + * Providers in this module will be accessible to both WMComponent and SysUIComponent scoped + * classes. They are in here because they are either needed globally or are inherently universal + * to the application. + * + * Note that just because a class might be used by both WM and SysUI does not necessarily mean that + * it should got into this module. If WM and SysUI might need the class for different purposes + * or different semantics, it may make sense to ask them to supply their own. Something like + * threading and concurrency provide a good example. Both components need + * Threads/Handlers/Executors, but they need separate instances of them in many cases. + * + * Please use discretion when adding things to the global scope. + */ +@Module +public class GlobalModule { + /** */ + @Provides + @Main + public SharedPreferences provideSharePreferences(Context context) { + return Prefs.get(context); + } + + /** */ + @Provides + public AmbientDisplayConfiguration provideAmbientDisplayConfiguration(Context context) { + return new AmbientDisplayConfiguration(context); + } + + /** */ + @Provides + @Singleton + public Choreographer providesChoreographer() { + return Choreographer.getInstance(); + } + + /** */ + @Provides + @Singleton + public DisplayMetrics provideDisplayMetrics(Context context) { + DisplayMetrics displayMetrics = new DisplayMetrics(); + context.getDisplay().getMetrics(displayMetrics); + return displayMetrics; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java index 9c55095e85e5..3d7c8ad4c43e 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java @@ -18,17 +18,6 @@ package com.android.systemui.dagger; import android.content.Context; -import com.android.systemui.BootCompleteCacheImpl; -import com.android.systemui.Dependency; -import com.android.systemui.InitController; -import com.android.systemui.SystemUIAppComponentFactory; -import com.android.systemui.dump.DumpManager; -import com.android.systemui.keyguard.KeyguardSliceProvider; -import com.android.systemui.onehanded.dagger.OneHandedModule; -import com.android.systemui.pip.phone.dagger.PipModule; -import com.android.systemui.statusbar.policy.ConfigurationController; -import com.android.systemui.util.InjectionInflationController; - import javax.inject.Singleton; import dagger.BindsInstance; @@ -37,18 +26,9 @@ import dagger.Component; /** * Root component for Dagger injection. */ -// TODO(b/162923491): Move most of these modules to SysUIComponent. @Singleton @Component(modules = { - DefaultComponentBinder.class, - DependencyProvider.class, - DependencyBinder.class, - OneHandedModule.class, - PipModule.class, - SystemServicesModule.class, - SystemUIBinder.class, - SystemUIModule.class, - SystemUIDefaultModule.class, + SysUISubcomponentModule.class, WMModule.class}) public interface GlobalRootComponent { @@ -72,53 +52,4 @@ public interface GlobalRootComponent { * Builder for a SysuiComponent. */ SysUIComponent.Builder getSysUIComponent(); - - /** - * Provides a BootCompleteCache. - */ - @Singleton - BootCompleteCacheImpl provideBootCacheImpl(); - - /** - * Creates a ContextComponentHelper. - */ - @Singleton - ConfigurationController getConfigurationController(); - - /** - * Creates a ContextComponentHelper. - */ - @Singleton - ContextComponentHelper getContextComponentHelper(); - - /** - * Main dependency providing module. - */ - @Singleton - Dependency createDependency(); - - /** */ - @Singleton - DumpManager createDumpManager(); - - /** - * Creates a InitController. - */ - @Singleton - InitController getInitController(); - - /** - * ViewInstanceCreator generates all Views that need injection. - */ - InjectionInflationController.ViewInstanceCreator.Factory createViewInstanceCreatorFactory(); - - /** - * Member injection into the supplied argument. - */ - void inject(SystemUIAppComponentFactory factory); - - /** - * Member injection into the supplied argument. - */ - void inject(KeyguardSliceProvider keyguardSliceProvider); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java index 9b527bfeda27..7281faf1a2c4 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java @@ -16,13 +16,33 @@ package com.android.systemui.dagger; +import com.android.systemui.BootCompleteCacheImpl; +import com.android.systemui.Dependency; +import com.android.systemui.InitController; +import com.android.systemui.SystemUIAppComponentFactory; +import com.android.systemui.dump.DumpManager; +import com.android.systemui.keyguard.KeyguardSliceProvider; +import com.android.systemui.onehanded.dagger.OneHandedModule; +import com.android.systemui.pip.phone.dagger.PipModule; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.util.InjectionInflationController; + import dagger.Subcomponent; /** * Dagger Subcomponent for Core SysUI. */ @SysUISingleton -@Subcomponent(modules = {}) +@Subcomponent(modules = { + DefaultComponentBinder.class, + DependencyProvider.class, + DependencyBinder.class, + OneHandedModule.class, + PipModule.class, + SystemServicesModule.class, + SystemUIBinder.class, + SystemUIModule.class, + SystemUIDefaultModule.class}) public interface SysUIComponent { /** @@ -32,4 +52,53 @@ public interface SysUIComponent { interface Builder { SysUIComponent build(); } + + /** + * Provides a BootCompleteCache. + */ + @SysUISingleton + BootCompleteCacheImpl provideBootCacheImpl(); + + /** + * Creates a ContextComponentHelper. + */ + @SysUISingleton + ConfigurationController getConfigurationController(); + + /** + * Creates a ContextComponentHelper. + */ + @SysUISingleton + ContextComponentHelper getContextComponentHelper(); + + /** + * Main dependency providing module. + */ + @SysUISingleton + Dependency createDependency(); + + /** */ + @SysUISingleton + DumpManager createDumpManager(); + + /** + * Creates a InitController. + */ + @SysUISingleton + InitController getInitController(); + + /** + * ViewInstanceCreator generates all Views that need injection. + */ + InjectionInflationController.ViewInstanceCreator.Factory createViewInstanceCreatorFactory(); + + /** + * Member injection into the supplied argument. + */ + void inject(SystemUIAppComponentFactory factory); + + /** + * Member injection into the supplied argument. + */ + void inject(KeyguardSliceProvider keyguardSliceProvider); } diff --git a/tests/AutoVerify/app2/src/com/android/test/autoverify/MainActivity.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUISubcomponentModule.java index 09ef47212622..aacc6939cf74 100644 --- a/tests/AutoVerify/app2/src/com/android/test/autoverify/MainActivity.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUISubcomponentModule.java @@ -13,3 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +package com.android.systemui.dagger; + +import dagger.Module; + +/** + * Dagger module for including the WMComponent. + */ +@Module(subcomponents = {SysUIComponent.class}) +public abstract class SysUISubcomponentModule { +} diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java index 251ce1304930..7fe9faf5258c 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java @@ -43,6 +43,7 @@ import android.hardware.display.ColorDisplayManager; import android.hardware.display.DisplayManager; import android.media.AudioManager; import android.media.MediaRouter2Manager; +import android.media.session.MediaSessionManager; import android.net.ConnectivityManager; import android.net.NetworkScoreManager; import android.net.wifi.WifiManager; @@ -71,8 +72,6 @@ import com.android.systemui.dagger.qualifiers.DisplayId; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.shared.system.PackageManagerWrapper; -import javax.inject.Singleton; - import dagger.Module; import dagger.Provides; @@ -82,49 +81,49 @@ import dagger.Provides; @Module public class SystemServicesModule { @Provides - @Singleton + @SysUISingleton static AccessibilityManager provideAccessibilityManager(Context context) { return context.getSystemService(AccessibilityManager.class); } @Provides - @Singleton + @SysUISingleton static ActivityManager provideActivityManager(Context context) { return context.getSystemService(ActivityManager.class); } - @Singleton + @SysUISingleton @Provides static AlarmManager provideAlarmManager(Context context) { return context.getSystemService(AlarmManager.class); } @Provides - @Singleton + @SysUISingleton static AudioManager provideAudioManager(Context context) { return context.getSystemService(AudioManager.class); } @Provides - @Singleton + @SysUISingleton static ColorDisplayManager provideColorDisplayManager(Context context) { return context.getSystemService(ColorDisplayManager.class); } @Provides - @Singleton + @SysUISingleton static ConnectivityManager provideConnectivityManagager(Context context) { return context.getSystemService(ConnectivityManager.class); } @Provides - @Singleton + @SysUISingleton static ContentResolver provideContentResolver(Context context) { return context.getContentResolver(); } @Provides - @Singleton + @SysUISingleton static DevicePolicyManager provideDevicePolicyManager(Context context) { return context.getSystemService(DevicePolicyManager.class); } @@ -136,44 +135,44 @@ public class SystemServicesModule { } @Provides - @Singleton + @SysUISingleton static DisplayManager provideDisplayManager(Context context) { return context.getSystemService(DisplayManager.class); } - @Singleton + @SysUISingleton @Provides static IActivityManager provideIActivityManager() { return ActivityManager.getService(); } - @Singleton + @SysUISingleton @Provides static IActivityTaskManager provideIActivityTaskManager() { return ActivityTaskManager.getService(); } @Provides - @Singleton + @SysUISingleton static IBatteryStats provideIBatteryStats() { return IBatteryStats.Stub.asInterface( ServiceManager.getService(BatteryStats.SERVICE_NAME)); } @Provides - @Singleton + @SysUISingleton static IDreamManager provideIDreamManager() { return IDreamManager.Stub.asInterface( ServiceManager.checkService(DreamService.DREAM_SERVICE)); } @Provides - @Singleton + @SysUISingleton static IPackageManager provideIPackageManager() { return IPackageManager.Stub.asInterface(ServiceManager.getService("package")); } - @Singleton + @SysUISingleton @Provides static IStatusBarService provideIStatusBarService() { return IStatusBarService.Stub.asInterface( @@ -187,32 +186,32 @@ public class SystemServicesModule { ServiceManager.getService(Context.WALLPAPER_SERVICE)); } - @Singleton + @SysUISingleton @Provides static IWindowManager provideIWindowManager() { return WindowManagerGlobal.getWindowManagerService(); } - @Singleton + @SysUISingleton @Provides static KeyguardManager provideKeyguardManager(Context context) { return context.getSystemService(KeyguardManager.class); } - @Singleton + @SysUISingleton @Provides static LatencyTracker provideLatencyTracker(Context context) { return LatencyTracker.getInstance(context); } - @Singleton + @SysUISingleton @Provides static LauncherApps provideLauncherApps(Context context) { return context.getSystemService(LauncherApps.class); } @SuppressLint("MissingPermission") - @Singleton + @SysUISingleton @Provides @Nullable static LocalBluetoothManager provideLocalBluetoothController(Context context, @@ -226,31 +225,36 @@ public class SystemServicesModule { } @Provides - @Singleton + static MediaSessionManager provideMediaSessionManager(Context context) { + return context.getSystemService(MediaSessionManager.class); + } + + @Provides + @SysUISingleton static NetworkScoreManager provideNetworkScoreManager(Context context) { return context.getSystemService(NetworkScoreManager.class); } - @Singleton + @SysUISingleton @Provides static NotificationManager provideNotificationManager(Context context) { return context.getSystemService(NotificationManager.class); } - @Singleton + @SysUISingleton @Provides static PackageManager providePackageManager(Context context) { return context.getPackageManager(); } - @Singleton + @SysUISingleton @Provides static PackageManagerWrapper providePackageManagerWrapper() { return PackageManagerWrapper.getInstance(); } /** */ - @Singleton + @SysUISingleton @Provides static PowerManager providePowerManager(Context context) { return context.getSystemService(PowerManager.class); @@ -263,51 +267,51 @@ public class SystemServicesModule { } @Provides - @Singleton + @SysUISingleton static SensorManager providesSensorManager(Context context) { return context.getSystemService(SensorManager.class); } - @Singleton + @SysUISingleton @Provides static SensorPrivacyManager provideSensorPrivacyManager(Context context) { return context.getSystemService(SensorPrivacyManager.class); } - @Singleton + @SysUISingleton @Provides static ShortcutManager provideShortcutManager(Context context) { return context.getSystemService(ShortcutManager.class); } @Provides - @Singleton + @SysUISingleton @Nullable static TelecomManager provideTelecomManager(Context context) { return context.getSystemService(TelecomManager.class); } @Provides - @Singleton + @SysUISingleton static TelephonyManager provideTelephonyManager(Context context) { return context.getSystemService(TelephonyManager.class); } @Provides - @Singleton + @SysUISingleton static TrustManager provideTrustManager(Context context) { return context.getSystemService(TrustManager.class); } @Provides - @Singleton + @SysUISingleton @Nullable static Vibrator provideVibrator(Context context) { return context.getSystemService(Vibrator.class); } @Provides - @Singleton + @SysUISingleton static UserManager provideUserManager(Context context) { return context.getSystemService(UserManager.class); } @@ -318,20 +322,20 @@ public class SystemServicesModule { } @Provides - @Singleton + @SysUISingleton @Nullable static WifiManager provideWifiManager(Context context) { return context.getSystemService(WifiManager.class); } - @Singleton + @SysUISingleton @Provides static WindowManager provideWindowManager(Context context) { return context.getSystemService(WindowManager.class); } @Provides - @Singleton + @SysUISingleton static RoleManager provideRoleManager(Context context) { return context.getSystemService(RoleManager.class); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java index 4fd31c7609e2..3b225d5313c1 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java @@ -29,6 +29,7 @@ import com.android.keyguard.KeyguardViewController; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dock.DockManager; import com.android.systemui.dock.DockManagerImpl; import com.android.systemui.doze.DozeHost; @@ -44,12 +45,14 @@ import com.android.systemui.stackdivider.DividerModule; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.phone.DozeServiceHost; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl; import com.android.systemui.statusbar.phone.NotificationGroupManager; +import com.android.systemui.statusbar.phone.NotificationShadeWindowControllerImpl; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.ShadeControllerImpl; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; @@ -59,10 +62,9 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl; import com.android.systemui.statusbar.policy.HeadsUpManager; -import com.android.systemui.wmshell.WindowManagerShellModule; +import com.android.systemui.wmshell.WMShellModule; import javax.inject.Named; -import javax.inject.Singleton; import dagger.Binds; import dagger.Module; @@ -75,14 +77,11 @@ import dagger.Provides; @Module(includes = { DividerModule.class, QSModule.class, - WindowManagerShellModule.class - }, - subcomponents = { - SysUIComponent.class + WMShellModule.class }) public abstract class SystemUIDefaultModule { - @Singleton + @SysUISingleton @Provides @Named(LEAK_REPORT_EMAIL_NAME) @Nullable @@ -98,19 +97,29 @@ public abstract class SystemUIDefaultModule { NotificationLockscreenUserManagerImpl notificationLockscreenUserManager); @Provides - @Singleton - static BatteryController provideBatteryController(Context context, - EnhancedEstimates enhancedEstimates, PowerManager powerManager, - BroadcastDispatcher broadcastDispatcher, @Main Handler mainHandler, + @SysUISingleton + static BatteryController provideBatteryController( + Context context, + EnhancedEstimates enhancedEstimates, + PowerManager powerManager, + BroadcastDispatcher broadcastDispatcher, + DemoModeController demoModeController, + @Main Handler mainHandler, @Background Handler bgHandler) { - BatteryController bC = new BatteryControllerImpl(context, enhancedEstimates, powerManager, - broadcastDispatcher, mainHandler, bgHandler); + BatteryController bC = new BatteryControllerImpl( + context, + enhancedEstimates, + powerManager, + broadcastDispatcher, + demoModeController, + mainHandler, + bgHandler); bC.init(); return bC; } @Binds - @Singleton + @SysUISingleton public abstract QSFactory bindQSFactory(QSFactoryImpl qsFactoryImpl); @Binds @@ -123,14 +132,14 @@ public abstract class SystemUIDefaultModule { @Binds abstract ShadeController provideShadeController(ShadeControllerImpl shadeController); - @Singleton + @SysUISingleton @Provides @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) static boolean provideAllowNotificationLongPress() { return true; } - @Singleton + @SysUISingleton @Provides static HeadsUpManagerPhone provideHeadsUpManagerPhone( Context context, @@ -146,7 +155,7 @@ public abstract class SystemUIDefaultModule { abstract HeadsUpManager bindHeadsUpManagerPhone(HeadsUpManagerPhone headsUpManagerPhone); @Provides - @Singleton + @SysUISingleton static Recents provideRecents(Context context, RecentsImplementation recentsImplementation, CommandQueue commandQueue) { return new Recents(context, recentsImplementation, commandQueue); @@ -161,5 +170,9 @@ public abstract class SystemUIDefaultModule { StatusBarKeyguardViewManager statusBarKeyguardViewManager); @Binds + abstract NotificationShadeWindowController bindNotificationShadeController( + NotificationShadeWindowControllerImpl notificationShadeWindowController); + + @Binds abstract DozeHost provideDozeHost(DozeServiceHost dozeServiceHost); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index f6db6d59bb6d..abfc2ab1c6e8 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -24,6 +24,7 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.BootCompleteCache; import com.android.systemui.BootCompleteCacheImpl; import com.android.systemui.assist.AssistModule; +import com.android.systemui.demomode.dagger.DemoModeModule; import com.android.systemui.doze.dagger.DozeComponent; import com.android.systemui.dump.DumpManager; import com.android.systemui.fragments.FragmentService; @@ -51,8 +52,6 @@ import com.android.systemui.util.settings.SettingsUtilModule; import com.android.systemui.util.time.SystemClock; import com.android.systemui.util.time.SystemClockImpl; -import javax.inject.Singleton; - import dagger.Binds; import dagger.BindsOptionalOf; import dagger.Module; @@ -65,6 +64,7 @@ import dagger.Provides; @Module(includes = { AssistModule.class, ConcurrencyModule.class, + DemoModeModule.class, LogModule.class, PeopleHubModule.class, SensorModule.class, @@ -87,7 +87,7 @@ public abstract class SystemUIModule { public abstract ContextComponentHelper bindComponentHelper( ContextComponentResolver componentHelper); - @Singleton + @SysUISingleton @Provides @Nullable static KeyguardLiftController provideKeyguardLiftController( @@ -108,7 +108,7 @@ public abstract class SystemUIModule { public abstract NotificationRowBinder bindNotificationRowBinder( NotificationRowBinderImpl notificationRowBinder); - @Singleton + @SysUISingleton @Provides static SysUiState provideSysUiState() { return new SysUiState(); @@ -129,7 +129,7 @@ public abstract class SystemUIModule { @BindsOptionalOf abstract StatusBar optionalStatusBar(); - @Singleton + @SysUISingleton @Binds abstract SystemClock bindSystemClock(SystemClockImpl systemClock); } diff --git a/packages/SystemUI/src/com/android/systemui/demomode/DemoMode.java b/packages/SystemUI/src/com/android/systemui/demomode/DemoMode.java new file mode 100644 index 000000000000..672ade2655a3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/demomode/DemoMode.java @@ -0,0 +1,70 @@ +/* + * 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.demomode; + +import com.google.android.collect.Lists; + +import java.util.ArrayList; +import java.util.List; + +/** + * Interface defining what it means to implement DemoMode. A DemoMode implementation should + * register with DemoModeController, providing a list of commands for wish to listen. + * + * If you only need to listen to commands, but *do not* care about demo mode state changes, you + * can implement DemoModeCommandReceiver instead + */ +public interface DemoMode extends DemoModeCommandReceiver { + + List<String> NO_COMMANDS = new ArrayList<>(); + + /** Provide a set of commands to listen to, only acceptable values are the COMMAND_* keys */ + default List<String> demoCommands() { + return NO_COMMANDS; + } + + String ACTION_DEMO = "com.android.systemui.demo"; + + String EXTRA_COMMAND = "command"; + + /** Enter and exit are non-register-able; override started/finished to observe these states */ + String COMMAND_ENTER = "enter"; + String COMMAND_EXIT = "exit"; + + /** Observable commands to register a listener for */ + String COMMAND_CLOCK = "clock"; + String COMMAND_BATTERY = "battery"; + String COMMAND_NETWORK = "network"; + String COMMAND_BARS = "bars"; + String COMMAND_STATUS = "status"; + String COMMAND_NOTIFICATIONS = "notifications"; + String COMMAND_VOLUME = "volume"; + String COMMAND_OPERATOR = "operator"; + + /** New keys need to be added here */ + List<String> COMMANDS = Lists.newArrayList( + COMMAND_BARS, + COMMAND_BATTERY, + COMMAND_CLOCK, + COMMAND_NETWORK, + COMMAND_NOTIFICATIONS, + COMMAND_OPERATOR, + COMMAND_STATUS, + COMMAND_VOLUME + ); +} + diff --git a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeAvailabilityTracker.kt b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeAvailabilityTracker.kt new file mode 100644 index 000000000000..16f415070b45 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeAvailabilityTracker.kt @@ -0,0 +1,109 @@ +/* + * 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.demomode + +import android.content.Context +import android.database.ContentObserver +import android.os.Handler +import android.os.Looper +import android.provider.Settings + +/** + * Class to track the availability of [DemoMode]. Use this class to track the availability and + * on/off state for DemoMode + * + * This class works by wrapping a content observer for the relevant keys related to DemoMode + * availability and current on/off state, and triggering callbacks. + */ +abstract class DemoModeAvailabilityTracker(val context: Context) { + var isInDemoMode = false + var isDemoModeAvailable = false + + init { + isInDemoMode = checkIsDemoModeOn() + isDemoModeAvailable = checkIsDemoModeAllowed() + } + + fun startTracking() { + val resolver = context.contentResolver + resolver.registerContentObserver( + Settings.Global.getUriFor(DEMO_MODE_ALLOWED), false, allowedObserver) + resolver.registerContentObserver( + Settings.Global.getUriFor(DEMO_MODE_ON), false, onObserver) + } + + fun stopTracking() { + val resolver = context.contentResolver + resolver.unregisterContentObserver(allowedObserver) + resolver.unregisterContentObserver(onObserver) + } + + abstract fun onDemoModeAvailabilityChanged() + abstract fun onDemoModeStarted() + abstract fun onDemoModeFinished() + + private fun checkIsDemoModeAllowed(): Boolean { + return Settings.Global + .getInt(context.contentResolver, DEMO_MODE_ALLOWED, 0) != 0 + } + + private fun checkIsDemoModeOn(): Boolean { + return Settings.Global.getInt(context.contentResolver, DEMO_MODE_ON, 0) != 0 + } + + private val allowedObserver = object : ContentObserver(Handler(Looper.getMainLooper())) { + override fun onChange(selfChange: Boolean) { + val allowed = checkIsDemoModeAllowed() + if (DEBUG) { + android.util.Log.d(TAG, "onChange: DEMO_MODE_ALLOWED changed: $allowed") + } + + if (isDemoModeAvailable == allowed) { + return + } + + isDemoModeAvailable = allowed + onDemoModeAvailabilityChanged() + } + } + + private val onObserver = object : ContentObserver(Handler(Looper.getMainLooper())) { + override fun onChange(selfChange: Boolean) { + val on = checkIsDemoModeOn() + + if (DEBUG) { + android.util.Log.d(TAG, "onChange: DEMO_MODE_ON changed: $on") + } + + if (isInDemoMode == on) { + return + } + + isInDemoMode = on + if (on) { + onDemoModeStarted() + } else { + onDemoModeFinished() + } + } + } +} + +private const val TAG = "DemoModeAvailabilityTracker" +private const val DEMO_MODE_ALLOWED = "sysui_demo_allowed" +private const val DEMO_MODE_ON = "sysui_tuner_demo_on" +private const val DEBUG = false diff --git a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeCommandReceiver.java b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeCommandReceiver.java new file mode 100644 index 000000000000..609536a4b8e8 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeCommandReceiver.java @@ -0,0 +1,35 @@ +/* + * 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.demomode; + +import android.os.Bundle; + +/** Defines the basic DemoMode command interface */ +public interface DemoModeCommandReceiver { + /** Override point to observe demo mode commands */ + void dispatchDemoCommand(String command, Bundle args); + + /** + * Demo mode starts due to receiving [COMMAND_ENTER] or receiving any other demo mode command + * while [DEMO_MODE_ALLOWED] is true but demo mode is off + */ + default void onDemoModeStarted() {} + + /** Demo mode exited */ + default void onDemoModeFinished() {} + +} diff --git a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt new file mode 100644 index 000000000000..c76f55631ac9 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt @@ -0,0 +1,249 @@ +/* + * 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.demomode + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.os.Bundle +import android.os.UserHandle +import android.util.Log +import com.android.systemui.Dumpable +import com.android.systemui.demomode.DemoMode.ACTION_DEMO +import com.android.systemui.dump.DumpManager +import com.android.systemui.statusbar.policy.CallbackController +import com.android.systemui.util.Assert +import com.android.systemui.util.settings.GlobalSettings +import java.io.FileDescriptor +import java.io.PrintWriter + +/** + * Handles system broadcasts for [DemoMode] + * + * Injected via [DemoModeModule] + */ +class DemoModeController constructor( + private val context: Context, + private val dumpManager: DumpManager, + private val globalSettings: GlobalSettings +) : CallbackController<DemoMode>, Dumpable { + + // Var updated when the availability tracker changes, or when we enter/exit demo mode in-process + var isInDemoMode = false + + var isAvailable = false + get() = tracker.isDemoModeAvailable + + private var initialized = false + + private val receivers = mutableListOf<DemoMode>() + private val receiverMap: Map<String, MutableList<DemoMode>> + + init { + val m = mutableMapOf<String, MutableList<DemoMode>>() + DemoMode.COMMANDS.map { command -> + m.put(command, mutableListOf()) + } + receiverMap = m + } + + fun initialize() { + if (initialized) { + throw IllegalStateException("Already initialized") + } + + initialized = true + + dumpManager.registerDumpable(TAG, this) + + // Due to DemoModeFragment running in systemui:tuner process, we have to observe for + // content changes to know if the setting turned on or off + tracker.startTracking() + + // TODO: We should probably exit demo mode if we booted up with it on + isInDemoMode = tracker.isInDemoMode + + val demoFilter = IntentFilter() + demoFilter.addAction(ACTION_DEMO) + context.registerReceiverAsUser(broadcastReceiver, UserHandle.ALL, demoFilter, + android.Manifest.permission.DUMP, null) + } + + override fun addCallback(listener: DemoMode) { + Assert.isMainThread() + + // Register this listener for its commands + val commands = listener.demoCommands() + + commands.forEach { command -> + if (!receiverMap.containsKey(command)) { + throw IllegalStateException("Command ($command) not recognized. " + + "See DemoMode.java for valid commands") + } + + receiverMap[command]!!.add(listener) + } + + receivers.add(listener) + if (isInDemoMode) { + listener.onDemoModeStarted() + } + } + + override fun removeCallback(listener: DemoMode) { + Assert.isMainThread() + + listener.demoCommands().forEach { command -> + receiverMap[command]!!.remove(listener) + } + + receivers.remove(listener) + } + + private fun setIsDemoModeAllowed(enabled: Boolean) { + // Turn off demo mode if it was on + if (isInDemoMode && !enabled) { + requestFinishDemoMode() + } + } + + private fun enterDemoMode() { + isInDemoMode = true + Assert.isMainThread() + receivers.forEach { r -> + r.onDemoModeStarted() + } + } + + private fun exitDemoMode() { + isInDemoMode = false + Assert.isMainThread() + receivers.forEach { r -> + r.onDemoModeFinished() + } + } + + fun dispatchDemoCommand(command: String, args: Bundle) { + Assert.isMainThread() + + if (DEBUG) { + Log.d(TAG, "dispatchDemoCommand: $command, args=$args") + } + + if (!isAvailable) { + return + } + + if (command == DemoMode.COMMAND_ENTER) { + enterDemoMode() + } else if (command == DemoMode.COMMAND_EXIT) { + exitDemoMode() + } else if (!isInDemoMode) { + enterDemoMode() + } + + // See? demo mode is easy now, you just notify the listeners when their command is called + receiverMap[command]!!.forEach { receiver -> + receiver.dispatchDemoCommand(command, args) + } + } + + override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) { + pw.println("DemoModeController state -") + pw.println(" isInDemoMode=$isInDemoMode") + pw.println(" isDemoModeAllowed=$isAvailable") + pw.print(" receivers=[") + receivers.forEach { recv -> + pw.print(" ${recv.javaClass.simpleName}") + } + pw.println(" ]") + pw.println(" receiverMap= [") + receiverMap.keys.forEach { command -> + pw.print(" $command : [") + val recvs = receiverMap[command]!!.map { receiver -> + receiver.javaClass.simpleName + }.joinToString(",") + pw.println("$recvs ]") + } + } + + private val tracker = object : DemoModeAvailabilityTracker(context) { + override fun onDemoModeAvailabilityChanged() { + setIsDemoModeAllowed(isDemoModeAvailable) + } + + override fun onDemoModeStarted() { + if (this@DemoModeController.isInDemoMode != isInDemoMode) { + enterDemoMode() + } + } + + override fun onDemoModeFinished() { + if (this@DemoModeController.isInDemoMode != isInDemoMode) { + exitDemoMode() + } + } + } + + private val broadcastReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + if (DEBUG) { + Log.v(TAG, "onReceive: $intent") + } + + val action = intent.action + if (!ACTION_DEMO.equals(action)) { + return + } + + val bundle = intent.extras ?: return + val command = bundle.getString("command", "").trim().toLowerCase() + if (command.length == 0) { + return + } + + try { + dispatchDemoCommand(command, bundle) + } catch (t: Throwable) { + Log.w(TAG, "Error running demo command, intent=$intent $t") + } + } + } + + fun requestSetDemoModeAllowed(allowed: Boolean) { + setGlobal(DEMO_MODE_ALLOWED, if (allowed) 1 else 0) + } + + fun requestStartDemoMode() { + setGlobal(DEMO_MODE_ON, 1) + } + + fun requestFinishDemoMode() { + setGlobal(DEMO_MODE_ON, 0) + } + + private fun setGlobal(key: String, value: Int) { + globalSettings.putInt(key, value) + } +} + +private const val TAG = "DemoModeController" +private const val DEMO_MODE_ALLOWED = "sysui_demo_allowed" +private const val DEMO_MODE_ON = "sysui_tuner_demo_on" + +private const val DEBUG = false diff --git a/packages/SystemUI/src/com/android/systemui/demomode/dagger/DemoModeModule.java b/packages/SystemUI/src/com/android/systemui/demomode/dagger/DemoModeModule.java new file mode 100644 index 000000000000..de9affb5c748 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/demomode/dagger/DemoModeModule.java @@ -0,0 +1,45 @@ +/* + * 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.demomode.dagger; + +import android.content.Context; + +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.demomode.DemoModeController; +import com.android.systemui.dump.DumpManager; +import com.android.systemui.util.settings.GlobalSettings; + +import dagger.Module; +import dagger.Provides; + +/** + * Dagger module providing {@link DemoModeController} + */ +@Module +public abstract class DemoModeModule { + /** Provides DemoModeController */ + @Provides + @SysUISingleton + static DemoModeController provideDemoModeController( + Context context, + DumpManager dumpManager, + GlobalSettings globalSettings) { + DemoModeController dmc = new DemoModeController(context, dumpManager, globalSettings); + dmc.initialize(); + return /*run*/dmc; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dock/DockManagerImpl.java b/packages/SystemUI/src/com/android/systemui/dock/DockManagerImpl.java index efc39058be39..8f399754730b 100644 --- a/packages/SystemUI/src/com/android/systemui/dock/DockManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/dock/DockManagerImpl.java @@ -16,10 +16,11 @@ package com.android.systemui.dock; +import com.android.systemui.dagger.SysUISingleton; + import javax.inject.Inject; -import javax.inject.Singleton; -@Singleton +@SysUISingleton public class DockManagerImpl implements DockManager { @Inject diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java index a311a450c6b7..99d2651ae9ea 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java @@ -24,6 +24,7 @@ import androidx.annotation.NonNull; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; import java.io.FileDescriptor; @@ -32,14 +33,13 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import javax.inject.Inject; -import javax.inject.Singleton; /** * Logs doze events for debugging and triaging purposes. Logs are dumped in bugreports or on demand: * adb shell dumpsys activity service com.android.systemui/.SystemUIService \ * dependency DumpController DozeLog,DozeStats */ -@Singleton +@SysUISingleton public class DozeLog implements Dumpable { private final DozeLogger mLogger; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java index 19b0ea1db04e..1a1cc072c6bf 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java @@ -33,6 +33,9 @@ import java.io.PrintWriter; import javax.inject.Inject; +import dagger.Reusable; + +@Reusable // Don't create multiple DozeServices. public class DozeService extends DreamService implements DozeMachine.Service, RequestDoze, PluginListener<DozeServicePlugin> { private static final String TAG = "DozeService"; @@ -57,7 +60,7 @@ public class DozeService extends DreamService setWindowless(true); mPluginManager.addPluginListener(this, DozeServicePlugin.class, false /* allowMultiple */); - DozeComponent dozeComponent = mDozeComponentBuilder.build(this); + DozeComponent dozeComponent = mDozeComponentBuilder.build(); mDozeMachine = dozeComponent.getDozeMachine(); } diff --git a/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeComponent.java b/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeComponent.java index e925927e7564..247285434df9 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeComponent.java +++ b/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeComponent.java @@ -19,7 +19,6 @@ package com.android.systemui.doze.dagger; import com.android.systemui.doze.DozeMachine; import com.android.systemui.doze.DozeService; -import dagger.BindsInstance; import dagger.Subcomponent; /** @@ -31,7 +30,7 @@ public interface DozeComponent { /** Simple Builder for {@link DozeComponent}. */ @Subcomponent.Factory interface Builder { - DozeComponent build(@BindsInstance DozeService dozeService); + DozeComponent build(); } /** Supply a {@link DozeMachine}. */ diff --git a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt index bbb77504ec27..bfa478088cad 100644 --- a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt +++ b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt @@ -18,11 +18,11 @@ package com.android.systemui.dump import android.util.ArrayMap import com.android.systemui.Dumpable +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.log.LogBuffer import java.io.FileDescriptor import java.io.PrintWriter import javax.inject.Inject -import javax.inject.Singleton /** * Maintains a registry of things that should be dumped when a bug report is taken @@ -33,7 +33,7 @@ import javax.inject.Singleton * * See [DumpHandler] for more information on how and when this information is dumped. */ -@Singleton +@SysUISingleton class DumpManager @Inject constructor() { private val dumpables: MutableMap<String, RegisteredDumpable<Dumpable>> = ArrayMap() private val buffers: MutableMap<String, RegisteredDumpable<LogBuffer>> = ArrayMap() diff --git a/packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt b/packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt index 603cb672175d..0eab1afc4119 100644 --- a/packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt +++ b/packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt @@ -18,6 +18,7 @@ package com.android.systemui.dump import android.content.Context import android.util.Log +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.log.LogBuffer import com.android.systemui.util.io.Files import com.android.systemui.util.time.SystemClock @@ -33,7 +34,6 @@ import java.text.SimpleDateFormat import java.util.Locale import java.util.concurrent.TimeUnit import javax.inject.Inject -import javax.inject.Singleton /** * Dumps all [LogBuffer]s to a file @@ -41,7 +41,7 @@ import javax.inject.Singleton * Intended for emergencies, i.e. we're about to crash. This file can then be read at a later date * (usually in a bug report). */ -@Singleton +@SysUISingleton class LogBufferEulogizer( private val dumpManager: DumpManager, private val systemClock: SystemClock, diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java index e88886933d5f..0673879758ad 100644 --- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java +++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java @@ -21,6 +21,7 @@ import android.util.ArrayMap; import android.view.View; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.qs.QSFragment; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -30,7 +31,6 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Subcomponent; @@ -38,7 +38,7 @@ import dagger.Subcomponent; * Holds a map of root views to FragmentHostStates and generates them as needed. * Also dispatches the configuration changes to all current FragmentHostStates. */ -@Singleton +@SysUISingleton public class FragmentService implements Dumpable { private static final String TAG = "FragmentService"; diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java index b29c5b07c765..86c8565bf8ef 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java @@ -20,6 +20,7 @@ import android.os.ServiceManager; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.SystemUI; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.GlobalActions; import com.android.systemui.plugins.GlobalActions.GlobalActionsManager; import com.android.systemui.statusbar.CommandQueue; @@ -30,12 +31,11 @@ import com.android.systemui.statusbar.policy.ExtensionController.Extension; import javax.inject.Inject; import javax.inject.Provider; -import javax.inject.Singleton; /** * Manages power menu plugins and communicates power menu actions to the StatusBar. */ -@Singleton +@SysUISingleton public class GlobalActionsComponent extends SystemUI implements Callbacks, GlobalActionsManager { private final CommandQueue mCommandQueue; diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index ef51abb1404d..d213ac1132bb 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -132,7 +132,7 @@ import com.android.systemui.plugins.GlobalActions.GlobalActionsManager; import com.android.systemui.plugins.GlobalActionsPanelPlugin; import com.android.systemui.settings.CurrentUserContextTracker; import com.android.systemui.statusbar.NotificationShadeDepthController; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.EmergencyDialerConstants; @@ -148,6 +148,7 @@ import java.util.Set; import java.util.concurrent.Executor; import javax.inject.Inject; +import javax.inject.Provider; /** * Helper to show the global actions dialog. Each item is an {@link Action} that may show depending @@ -401,7 +402,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, if (mDialog != null) { if (!mDialog.isShowingControls() && shouldShowControls()) { mDialog.showControls(mControlsUiControllerOptional.get()); - } else if (shouldShowLockMessage()) { + } else if (shouldShowLockMessage(mDialog)) { mDialog.showLockMessage(); } } @@ -698,19 +699,17 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, mPowerAdapter = new MyPowerOptionsAdapter(); mDepthController.setShowingHomeControls(true); - GlobalActionsPanelPlugin.PanelViewController walletViewController = - getWalletViewController(); ControlsUiController uiController = null; if (mControlsUiControllerOptional.isPresent() && shouldShowControls()) { uiController = mControlsUiControllerOptional.get(); } ActionsDialog dialog = new ActionsDialog(mContext, mAdapter, mOverflowAdapter, - walletViewController, mDepthController, mSysuiColorExtractor, + this::getWalletViewController, mDepthController, mSysuiColorExtractor, mStatusBarService, mNotificationShadeWindowController, controlsAvailable(), uiController, mSysUiState, this::onRotate, mKeyguardShowing, mPowerAdapter); - if (shouldShowLockMessage()) { + if (shouldShowLockMessage(dialog)) { dialog.showLockMessage(); } dialog.setCanceledOnTouchOutside(false); // Handled by the custom class. @@ -2124,7 +2123,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, private MultiListLayout mGlobalActionsLayout; private Drawable mBackgroundDrawable; private final SysuiColorExtractor mColorExtractor; - private final GlobalActionsPanelPlugin.PanelViewController mWalletViewController; + private final Provider<GlobalActionsPanelPlugin.PanelViewController> mWalletFactory; + @Nullable private GlobalActionsPanelPlugin.PanelViewController mWalletViewController; private boolean mKeyguardShowing; private boolean mShowing; private float mScrimAlpha; @@ -2144,7 +2144,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, private TextView mLockMessage; ActionsDialog(Context context, MyAdapter adapter, MyOverflowAdapter overflowAdapter, - GlobalActionsPanelPlugin.PanelViewController walletViewController, + Provider<GlobalActionsPanelPlugin.PanelViewController> walletFactory, NotificationShadeDepthController depthController, SysuiColorExtractor sysuiColorExtractor, IStatusBarService statusBarService, NotificationShadeWindowController notificationShadeWindowController, @@ -2165,6 +2165,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, mSysUiState = sysuiState; mOnRotateCallback = onRotateCallback; mKeyguardShowing = keyguardShowing; + mWalletFactory = walletFactory; // Window initialization Window window = getWindow(); @@ -2187,7 +2188,6 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, window.getAttributes().setFitInsetsTypes(0 /* types */); setTitle(R.string.global_actions); - mWalletViewController = walletViewController; initializeLayout(); } @@ -2200,8 +2200,13 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, mControlsUiController.show(mControlsView, this::dismissForControlsActivity); } + private boolean isWalletViewAvailable() { + return mWalletViewController != null && mWalletViewController.getPanelContent() != null; + } + private void initializeWalletView() { - if (mWalletViewController == null || mWalletViewController.getPanelContent() == null) { + mWalletViewController = mWalletFactory.get(); + if (!isWalletViewAvailable()) { return; } @@ -2507,6 +2512,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, private void dismissWallet() { if (mWalletViewController != null) { mWalletViewController.onDismissed(); + // The wallet controller should not be re-used after being dismissed. + mWalletViewController = null; } } @@ -2648,18 +2655,12 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, && !mControlsServiceInfos.isEmpty(); } - private boolean walletViewAvailable() { - GlobalActionsPanelPlugin.PanelViewController walletViewController = - getWalletViewController(); - return walletViewController != null && walletViewController.getPanelContent() != null; - } - - private boolean shouldShowLockMessage() { + private boolean shouldShowLockMessage(ActionsDialog dialog) { boolean isLockedAfterBoot = mLockPatternUtils.getStrongAuthForUser(getCurrentUser().id) == STRONG_AUTH_REQUIRED_AFTER_BOOT; return !mKeyguardStateController.isUnlocked() && (!mShowLockScreenCardsAndControls || isLockedAfterBoot) - && (controlsAvailable() || walletViewAvailable()); + && (controlsAvailable() || dialog.isWalletViewAvailable()); } private void onPowerMenuLockScreenSettingsChanged() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java index f6f3b9985371..d1bbc3359917 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java @@ -17,18 +17,18 @@ package com.android.systemui.keyguard; import com.android.internal.policy.IKeyguardDismissCallback; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.UiBackground; import java.util.ArrayList; import java.util.concurrent.Executor; import javax.inject.Inject; -import javax.inject.Singleton; /** * Registry holding the current set of {@link IKeyguardDismissCallback}s. */ -@Singleton +@SysUISingleton public class DismissCallbackRegistry { private final ArrayList<DismissCallbackWrapper> mDismissCallbacks = new ArrayList<>(); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java index 4a33590f64d2..f527775449bf 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java @@ -19,13 +19,14 @@ package com.android.systemui.keyguard; import android.os.Handler; import android.os.Message; +import com.android.systemui.dagger.SysUISingleton; + import javax.inject.Inject; -import javax.inject.Singleton; /** * Dispatches the lifecycles keyguard gets from WindowManager on the main thread. */ -@Singleton +@SysUISingleton public class KeyguardLifecyclesDispatcher { static final int SCREEN_TURNING_ON = 0; diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java index 834bca55103a..084e84a7a77a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java @@ -19,17 +19,17 @@ package com.android.systemui.keyguard; import android.os.Trace; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import java.io.FileDescriptor; import java.io.PrintWriter; import javax.inject.Inject; -import javax.inject.Singleton; /** * Tracks the screen lifecycle. */ -@Singleton +@SysUISingleton public class ScreenLifecycle extends Lifecycle<ScreenLifecycle.Observer> implements Dumpable { public static final int SCREEN_OFF = 0; diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java index d17f2f621ec8..5161deb0e4de 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.os.Trace; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -27,12 +28,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import javax.inject.Inject; -import javax.inject.Singleton; /** * Tracks the wakefulness lifecycle. */ -@Singleton +@SysUISingleton public class WakefulnessLifecycle extends Lifecycle<WakefulnessLifecycle.Observer> implements Dumpable { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java index fc789a6fa4bc..7c5dcd8960c4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java @@ -24,20 +24,19 @@ import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardViewController; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.keyguard.KeyguardViewMediator; -import com.android.systemui.plugins.FalsingManager; import com.android.systemui.navigationbar.NavigationModeController; +import com.android.systemui.plugins.FalsingManager; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.InjectionInflationController; import java.util.concurrent.Executor; -import javax.inject.Singleton; - import dagger.Lazy; import dagger.Module; import dagger.Provides; @@ -51,7 +50,7 @@ public class KeyguardModule { * Provides our instance of KeyguardViewMediator which is considered optional. */ @Provides - @Singleton + @SysUISingleton public static KeyguardViewMediator newKeyguardViewMediator( Context context, FalsingManager falsingManager, diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java index 16f76deca6c6..6db408659c96 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java @@ -20,6 +20,7 @@ import android.content.ContentResolver; import android.os.Build; import android.os.Looper; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; import com.android.systemui.log.LogBuffer; @@ -27,8 +28,6 @@ import com.android.systemui.log.LogcatEchoTracker; import com.android.systemui.log.LogcatEchoTrackerDebug; import com.android.systemui.log.LogcatEchoTrackerProd; -import javax.inject.Singleton; - import dagger.Module; import dagger.Provides; @@ -39,7 +38,7 @@ import dagger.Provides; public class LogModule { /** Provides a logging buffer for doze-related logs. */ @Provides - @Singleton + @SysUISingleton @DozeLog public static LogBuffer provideDozeLogBuffer( LogcatEchoTracker bufferFilter, @@ -51,7 +50,7 @@ public class LogModule { /** Provides a logging buffer for all logs related to the data layer of notifications. */ @Provides - @Singleton + @SysUISingleton @NotificationLog public static LogBuffer provideNotificationsLogBuffer( LogcatEchoTracker bufferFilter, @@ -63,7 +62,7 @@ public class LogModule { /** Provides a logging buffer for all logs related to managing notification sections. */ @Provides - @Singleton + @SysUISingleton @NotificationSectionLog public static LogBuffer provideNotificationSectionLogBuffer( LogcatEchoTracker bufferFilter, @@ -75,7 +74,7 @@ public class LogModule { /** Provides a logging buffer for all logs related to the data layer of notifications. */ @Provides - @Singleton + @SysUISingleton @NotifInteractionLog public static LogBuffer provideNotifInteractionLogBuffer( LogcatEchoTracker echoTracker, @@ -87,7 +86,7 @@ public class LogModule { /** Provides a logging buffer for all logs related to Quick Settings. */ @Provides - @Singleton + @SysUISingleton @QSLog public static LogBuffer provideQuickSettingsLogBuffer( LogcatEchoTracker bufferFilter, @@ -99,7 +98,7 @@ public class LogModule { /** Provides a logging buffer for {@link com.android.systemui.broadcast.BroadcastDispatcher} */ @Provides - @Singleton + @SysUISingleton @BroadcastDispatcherLog public static LogBuffer provideBroadcastDispatcherLogBuffer( LogcatEchoTracker bufferFilter, @@ -111,7 +110,7 @@ public class LogModule { /** Allows logging buffers to be tweaked via adb on debug builds but not on prod builds. */ @Provides - @Singleton + @SysUISingleton public static LogcatEchoTracker provideLogcatEchoTracker( ContentResolver contentResolver, @Main Looper looper) { diff --git a/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt index f9c6307394e8..094ece27fc8e 100644 --- a/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt @@ -17,6 +17,7 @@ package com.android.systemui.media import android.view.View +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState @@ -24,13 +25,12 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.notification.stack.MediaHeaderView import com.android.systemui.statusbar.phone.KeyguardBypassController import javax.inject.Inject -import javax.inject.Singleton /** * A class that controls the media notifications on the lock screen, handles its visibility and * is responsible for the embedding of he media experience. */ -@Singleton +@SysUISingleton class KeyguardMediaController @Inject constructor( private val mediaHost: MediaHost, private val bypassController: KeyguardBypassController, diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt index b993faabe9b1..a003d8365810 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt @@ -12,11 +12,12 @@ import android.view.ViewGroup import android.widget.LinearLayout import androidx.annotation.VisibleForTesting import com.android.systemui.R +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager import com.android.systemui.qs.PageIndicator -import com.android.systemui.statusbar.notification.VisualStabilityManager +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.Utils import com.android.systemui.util.animation.UniqueObjectHostView @@ -25,7 +26,6 @@ import com.android.systemui.util.concurrency.DelayableExecutor import java.util.TreeMap import javax.inject.Inject import javax.inject.Provider -import javax.inject.Singleton private const val TAG = "MediaCarouselController" private val settingsIntent = Intent().setAction(ACTION_MEDIA_CONTROLS_SETTINGS) @@ -34,7 +34,7 @@ private val settingsIntent = Intent().setAction(ACTION_MEDIA_CONTROLS_SETTINGS) * Class that is responsible for keeping the view carousel up to date. * This also handles changes in state and applies them to the media carousel like the expansion. */ -@Singleton +@SysUISingleton class MediaCarouselController @Inject constructor( private val context: Context, private val mediaControlPanelFactory: Provider<MediaControlPanel>, @@ -42,7 +42,7 @@ class MediaCarouselController @Inject constructor( private val mediaHostStatesManager: MediaHostStatesManager, private val activityStarter: ActivityStarter, @Main executor: DelayableExecutor, - mediaManager: MediaDataFilter, + mediaManager: MediaDataManager, configurationController: ConfigurationController, falsingManager: FalsingManager ) { @@ -155,6 +155,7 @@ class MediaCarouselController @Inject constructor( inflateSettingsButton() mediaContent = mediaCarousel.requireViewById(R.id.media_carousel) configurationController.addCallback(configListener) + // TODO (b/162832756): remove visual stability manager when migrating to new pipeline visualStabilityCallback = VisualStabilityManager.Callback { if (needsReordering) { needsReordering = false diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt index d0642ccf9714..aa3699e9a22b 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt @@ -17,65 +17,48 @@ package com.android.systemui.media import javax.inject.Inject -import javax.inject.Singleton /** - * Combines updates from [MediaDataManager] with [MediaDeviceManager]. + * Combines [MediaDataManager.Listener] events with [MediaDeviceManager.Listener] events. */ -@Singleton -class MediaDataCombineLatest @Inject constructor( - private val dataSource: MediaDataManager, - private val deviceSource: MediaDeviceManager -) { +class MediaDataCombineLatest @Inject constructor() : MediaDataManager.Listener, + MediaDeviceManager.Listener { + private val listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf() private val entries: MutableMap<String, Pair<MediaData?, MediaDeviceData?>> = mutableMapOf() - init { - dataSource.addListener(object : MediaDataManager.Listener { - override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) { - if (oldKey != null && oldKey != key && entries.contains(oldKey)) { - entries[key] = data to entries.remove(oldKey)?.second - update(key, oldKey) - } else { - entries[key] = data to entries[key]?.second - update(key, key) - } - } - override fun onMediaDataRemoved(key: String) { - remove(key) - } - }) - deviceSource.addListener(object : MediaDeviceManager.Listener { - override fun onMediaDeviceChanged( - key: String, - oldKey: String?, - data: MediaDeviceData? - ) { - if (oldKey != null && oldKey != key && entries.contains(oldKey)) { - entries[key] = entries.remove(oldKey)?.first to data - update(key, oldKey) - } else { - entries[key] = entries[key]?.first to data - update(key, key) - } - } - override fun onKeyRemoved(key: String) { - remove(key) - } - }) + override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) { + if (oldKey != null && oldKey != key && entries.contains(oldKey)) { + entries[key] = data to entries.remove(oldKey)?.second + update(key, oldKey) + } else { + entries[key] = data to entries[key]?.second + update(key, key) + } } - /** - * Get a map of all non-null data entries - */ - fun getData(): Map<String, MediaData> { - return entries.filter { - (key, pair) -> pair.first != null && pair.second != null - }.mapValues { - (key, pair) -> pair.first!!.copy(device = pair.second) + override fun onMediaDataRemoved(key: String) { + remove(key) + } + + override fun onMediaDeviceChanged( + key: String, + oldKey: String?, + data: MediaDeviceData? + ) { + if (oldKey != null && oldKey != key && entries.contains(oldKey)) { + entries[key] = entries.remove(oldKey)?.first to data + update(key, oldKey) + } else { + entries[key] = entries[key]?.first to data + update(key, key) } } + override fun onKeyRemoved(key: String) { + remove(key) + } + /** * Add a listener for [MediaData] changes that has been combined with latest [MediaDeviceData]. */ diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt index 24ca9708a4e3..0664a41f841d 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt @@ -24,7 +24,6 @@ import com.android.systemui.settings.CurrentUserTracker import com.android.systemui.statusbar.NotificationLockscreenUserManager import java.util.concurrent.Executor import javax.inject.Inject -import javax.inject.Singleton private const val TAG = "MediaDataFilter" private const val DEBUG = true @@ -33,24 +32,24 @@ private const val DEBUG = true * Filters data updates from [MediaDataCombineLatest] based on the current user ID, and handles user * switches (removing entries for the previous user, adding back entries for the current user) * - * This is added downstream of [MediaDataManager] since we may still need to handle callbacks from - * background users (e.g. timeouts) that UI classes should ignore. - * Instead, UI classes should listen to this so they can stay in sync with the current user. + * This is added at the end of the pipeline since we may still need to handle callbacks from + * background users (e.g. timeouts). */ -@Singleton class MediaDataFilter @Inject constructor( - private val dataSource: MediaDataCombineLatest, private val broadcastDispatcher: BroadcastDispatcher, private val mediaResumeListener: MediaResumeListener, - private val mediaDataManager: MediaDataManager, private val lockscreenUserManager: NotificationLockscreenUserManager, @Main private val executor: Executor ) : MediaDataManager.Listener { private val userTracker: CurrentUserTracker - private val listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf() + private val _listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf() + internal val listeners: Set<MediaDataManager.Listener> + get() = _listeners.toSet() + internal lateinit var mediaDataManager: MediaDataManager - // The filtered mediaEntries, which will be a subset of all mediaEntries in MediaDataManager - private val mediaEntries: LinkedHashMap<String, MediaData> = LinkedHashMap() + private val allEntries: LinkedHashMap<String, MediaData> = LinkedHashMap() + // The filtered userEntries, which will be a subset of all userEntries in MediaDataManager + private val userEntries: LinkedHashMap<String, MediaData> = LinkedHashMap() init { userTracker = object : CurrentUserTracker(broadcastDispatcher) { @@ -60,31 +59,34 @@ class MediaDataFilter @Inject constructor( } } userTracker.startTracking() - dataSource.addListener(this) } override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) { + if (oldKey != null && oldKey != key) { + allEntries.remove(oldKey) + } + allEntries.put(key, data) + if (!lockscreenUserManager.isCurrentProfile(data.userId)) { return } - if (oldKey != null) { - mediaEntries.remove(oldKey) + if (oldKey != null && oldKey != key) { + userEntries.remove(oldKey) } - mediaEntries.put(key, data) + userEntries.put(key, data) // Notify listeners - val listenersCopy = listeners.toSet() - listenersCopy.forEach { + listeners.forEach { it.onMediaDataLoaded(key, oldKey, data) } } override fun onMediaDataRemoved(key: String) { - mediaEntries.remove(key)?.let { + allEntries.remove(key) + userEntries.remove(key)?.let { // Only notify listeners if something actually changed - val listenersCopy = listeners.toSet() - listenersCopy.forEach { + listeners.forEach { it.onMediaDataRemoved(key) } } @@ -93,11 +95,11 @@ class MediaDataFilter @Inject constructor( @VisibleForTesting internal fun handleUserSwitched(id: Int) { // If the user changes, remove all current MediaData objects and inform listeners - val listenersCopy = listeners.toSet() - val keyCopy = mediaEntries.keys.toMutableList() + val listenersCopy = listeners + val keyCopy = userEntries.keys.toMutableList() // Clear the list first, to make sure callbacks from listeners if we have any entries // are up to date - mediaEntries.clear() + userEntries.clear() keyCopy.forEach { if (DEBUG) Log.d(TAG, "Removing $it after user change") listenersCopy.forEach { listener -> @@ -105,10 +107,10 @@ class MediaDataFilter @Inject constructor( } } - dataSource.getData().forEach { (key, data) -> + allEntries.forEach { (key, data) -> if (lockscreenUserManager.isCurrentProfile(data.userId)) { if (DEBUG) Log.d(TAG, "Re-adding $key after user change") - mediaEntries.put(key, data) + userEntries.put(key, data) listenersCopy.forEach { listener -> listener.onMediaDataLoaded(key, null, data) } @@ -121,7 +123,7 @@ class MediaDataFilter @Inject constructor( */ fun onSwipeToDismiss() { if (DEBUG) Log.d(TAG, "Media carousel swiped away") - val mediaKeys = mediaEntries.keys.toSet() + val mediaKeys = userEntries.keys.toSet() mediaKeys.forEach { mediaDataManager.setTimedOut(it, timedOut = true) } @@ -130,7 +132,7 @@ class MediaDataFilter @Inject constructor( /** * Are there any media notifications active? */ - fun hasActiveMedia() = mediaEntries.any { it.value.active } + fun hasActiveMedia() = userEntries.any { it.value.active } /** * Are there any media entries we should display? @@ -138,7 +140,7 @@ class MediaDataFilter @Inject constructor( * If resumption is disabled, we only want to show active players */ fun hasAnyMedia() = if (mediaResumeListener.isResumptionEnabled()) { - mediaEntries.isNotEmpty() + userEntries.isNotEmpty() } else { hasActiveMedia() } @@ -146,10 +148,10 @@ class MediaDataFilter @Inject constructor( /** * Add a listener for filtered [MediaData] changes */ - fun addListener(listener: MediaDataManager.Listener) = listeners.add(listener) + fun addListener(listener: MediaDataManager.Listener) = _listeners.add(listener) /** * Remove a listener that was registered with addListener */ - fun removeListener(listener: MediaDataManager.Listener) = listeners.remove(listener) -}
\ No newline at end of file + fun removeListener(listener: MediaDataManager.Listener) = _listeners.remove(listener) +} diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt index bff334e92366..686531acb6f9 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt @@ -42,6 +42,7 @@ import com.android.internal.graphics.ColorUtils import com.android.systemui.Dumpable import com.android.systemui.R import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dump.DumpManager @@ -56,9 +57,6 @@ import java.io.IOException import java.io.PrintWriter import java.util.concurrent.Executor import javax.inject.Inject -import javax.inject.Singleton -import kotlin.collections.ArrayList -import kotlin.collections.LinkedHashMap // URI fields to try loading album art from private val ART_URIS = arrayOf( @@ -91,7 +89,7 @@ fun isMediaNotification(sbn: StatusBarNotification): Boolean { /** * A class that facilitates management and loading of Media Data, ready for binding. */ -@Singleton +@SysUISingleton class MediaDataManager( private val context: Context, @Background private val backgroundExecutor: Executor, @@ -101,12 +99,23 @@ class MediaDataManager( dumpManager: DumpManager, mediaTimeoutListener: MediaTimeoutListener, mediaResumeListener: MediaResumeListener, + mediaSessionBasedFilter: MediaSessionBasedFilter, + mediaDeviceManager: MediaDeviceManager, + mediaDataCombineLatest: MediaDataCombineLatest, + private val mediaDataFilter: MediaDataFilter, private val activityStarter: ActivityStarter, private var useMediaResumption: Boolean, private val useQsMediaPlayer: Boolean ) : Dumpable { - private val listeners: MutableSet<Listener> = mutableSetOf() + // Internal listeners are part of the internal pipeline. External listeners (those registered + // with [MediaDeviceManager.addListener]) receive events after they have propagated through + // the internal pipeline. + // Another way to think of the distinction between internal and external listeners is the + // following. Internal listeners are listeners that MediaDataManager depends on, and external + // listeners are listeners that depend on MediaDataManager. + // TODO(b/159539991#comment5): Move internal listeners to separate package. + private val internalListeners: MutableSet<Listener> = mutableSetOf() private val mediaEntries: LinkedHashMap<String, MediaData> = LinkedHashMap() internal var appsBlockedFromResume: MutableSet<String> = Utils.getBlockedMediaApps(context) set(value) { @@ -130,9 +139,14 @@ class MediaDataManager( broadcastDispatcher: BroadcastDispatcher, mediaTimeoutListener: MediaTimeoutListener, mediaResumeListener: MediaResumeListener, + mediaSessionBasedFilter: MediaSessionBasedFilter, + mediaDeviceManager: MediaDeviceManager, + mediaDataCombineLatest: MediaDataCombineLatest, + mediaDataFilter: MediaDataFilter, activityStarter: ActivityStarter ) : this(context, backgroundExecutor, foregroundExecutor, mediaControllerFactory, broadcastDispatcher, dumpManager, mediaTimeoutListener, mediaResumeListener, + mediaSessionBasedFilter, mediaDeviceManager, mediaDataCombineLatest, mediaDataFilter, activityStarter, Utils.useMediaResumption(context), Utils.useQsMediaPlayer(context)) private val appChangeReceiver = object : BroadcastReceiver() { @@ -155,12 +169,26 @@ class MediaDataManager( init { dumpManager.registerDumpable(TAG, this) + + // Initialize the internal processing pipeline. The listeners at the front of the pipeline + // are set as internal listeners so that they receive events. From there, events are + // propagated through the pipeline. The end of the pipeline is currently mediaDataFilter, + // so it is responsible for dispatching events to external listeners. To achieve this, + // external listeners that are registered with [MediaDataManager.addListener] are actually + // registered as listeners to mediaDataFilter. + addInternalListener(mediaTimeoutListener) + addInternalListener(mediaResumeListener) + addInternalListener(mediaSessionBasedFilter) + mediaSessionBasedFilter.addListener(mediaDeviceManager) + mediaSessionBasedFilter.addListener(mediaDataCombineLatest) + mediaDeviceManager.addListener(mediaDataCombineLatest) + mediaDataCombineLatest.addListener(mediaDataFilter) + + // Set up links back into the pipeline for listeners that need to send events upstream. mediaTimeoutListener.timeoutCallback = { token: String, timedOut: Boolean -> setTimedOut(token, timedOut) } - addListener(mediaTimeoutListener) - mediaResumeListener.setManager(this) - addListener(mediaResumeListener) + mediaDataFilter.mediaDataManager = this val suspendFilter = IntentFilter(Intent.ACTION_PACKAGES_SUSPENDED) broadcastDispatcher.registerReceiver(appChangeReceiver, suspendFilter, null, UserHandle.ALL) @@ -198,10 +226,9 @@ class MediaDataManager( private fun removeAllForPackage(packageName: String) { Assert.isMainThread() - val listenersCopy = listeners.toSet() val toRemove = mediaEntries.filter { it.value.packageName == packageName } toRemove.forEach { - removeEntry(it.key, listenersCopy) + removeEntry(it.key) } } @@ -261,12 +288,45 @@ class MediaDataManager( /** * Add a listener for changes in this class */ - fun addListener(listener: Listener) = listeners.add(listener) + fun addListener(listener: Listener) { + // mediaDataFilter is the current end of the internal pipeline. Register external + // listeners as listeners to it. + mediaDataFilter.addListener(listener) + } /** * Remove a listener for changes in this class */ - fun removeListener(listener: Listener) = listeners.remove(listener) + fun removeListener(listener: Listener) { + // Since mediaDataFilter is the current end of the internal pipelie, external listeners + // have been registered to it. So, they need to be removed from it too. + mediaDataFilter.removeListener(listener) + } + + /** + * Add a listener for internal events. + */ + private fun addInternalListener(listener: Listener) = internalListeners.add(listener) + + /** + * Notify internal listeners of loaded event. + * + * External listeners registered with [addListener] will be notified after the event propagates + * through the internal listener pipeline. + */ + private fun notifyMediaDataLoaded(key: String, oldKey: String?, info: MediaData) { + internalListeners.forEach { it.onMediaDataLoaded(key, oldKey, info) } + } + + /** + * Notify internal listeners of removed event. + * + * External listeners registered with [addListener] will be notified after the event propagates + * through the internal listener pipeline. + */ + private fun notifyMediaDataRemoved(key: String) { + internalListeners.forEach { it.onMediaDataRemoved(key) } + } /** * Called whenever the player has been paused or stopped for a while, or swiped from QQS. @@ -284,16 +344,13 @@ class MediaDataManager( } } - private fun removeEntry(key: String, listenersCopy: Set<Listener>) { + private fun removeEntry(key: String) { mediaEntries.remove(key) - listenersCopy.forEach { - it.onMediaDataRemoved(key) - } + notifyMediaDataRemoved(key) } fun dismissMediaData(key: String, delay: Long) { - val listenersCopy = listeners.toSet() - foregroundExecutor.executeDelayed({ removeEntry(key, listenersCopy) }, delay) + foregroundExecutor.executeDelayed({ removeEntry(key) }, delay) } private fun loadMediaDataInBgForResumption( @@ -422,7 +479,7 @@ class MediaDataManager( val runnable = if (action.actionIntent != null) { Runnable { if (action.isAuthenticationRequired()) { - activityStarter.dismissKeyguardThenExecute ({ + activityStarter.dismissKeyguardThenExecute({ var result = sendPendingIntent(action.actionIntent) result }, {}, true) @@ -550,10 +607,7 @@ class MediaDataManager( if (mediaEntries.containsKey(key)) { // Otherwise this was removed already mediaEntries.put(key, data) - val listenersCopy = listeners.toSet() - listenersCopy.forEach { - it.onMediaDataLoaded(key, oldKey, data) - } + notifyMediaDataLoaded(key, oldKey, data) } } @@ -570,31 +624,21 @@ class MediaDataManager( val pkg = removed?.packageName val migrate = mediaEntries.put(pkg, updated) == null // Notify listeners of "new" controls when migrating or removed and update when not - val listenersCopy = listeners.toSet() if (migrate) { - listenersCopy.forEach { - it.onMediaDataLoaded(pkg, key, updated) - } + notifyMediaDataLoaded(pkg, key, updated) } else { // Since packageName is used for the key of the resumption controls, it is // possible that another notification has already been reused for the resumption // controls of this package. In this case, rather than renaming this player as // packageName, just remove it and then send a update to the existing resumption // controls. - listenersCopy.forEach { - it.onMediaDataRemoved(key) - } - listenersCopy.forEach { - it.onMediaDataLoaded(pkg, pkg, updated) - } + notifyMediaDataRemoved(key) + notifyMediaDataLoaded(pkg, pkg, updated) } return } if (removed != null) { - val listenersCopy = listeners.toSet() - listenersCopy.forEach { - it.onMediaDataRemoved(key) - } + notifyMediaDataRemoved(key) } } @@ -614,17 +658,31 @@ class MediaDataManager( if (!useMediaResumption) { // Remove any existing resume controls - val listenersCopy = listeners.toSet() val filtered = mediaEntries.filter { !it.value.active } filtered.forEach { mediaEntries.remove(it.key) - listenersCopy.forEach { listener -> - listener.onMediaDataRemoved(it.key) - } + notifyMediaDataRemoved(it.key) } } } + /** + * Invoked when the user has dismissed the media carousel + */ + fun onSwipeToDismiss() = mediaDataFilter.onSwipeToDismiss() + + /** + * Are there any media notifications active? + */ + fun hasActiveMedia() = mediaDataFilter.hasActiveMedia() + + /** + * Are there any media entries we should display? + * If resumption is enabled, this will include inactive players + * If resumption is disabled, we only want to show active players + */ + fun hasAnyMedia() = mediaDataFilter.hasAnyMedia() + interface Listener { /** @@ -644,7 +702,8 @@ class MediaDataManager( override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) { pw.apply { - println("listeners: $listeners") + println("internalListeners: $internalListeners") + println("externalListeners: ${mediaDataFilter.listeners}") println("mediaEntries: $mediaEntries") println("useMediaResumption: $useMediaResumption") println("appsBlockedFromResume: $appsBlockedFromResume") diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt index ae7f66b5ac48..2bc908be055c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt @@ -24,34 +24,32 @@ import androidx.annotation.MainThread import androidx.annotation.WorkerThread import com.android.settingslib.media.LocalMediaManager import com.android.settingslib.media.MediaDevice +import com.android.systemui.Dumpable +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.Dumpable import com.android.systemui.dump.DumpManager import java.io.FileDescriptor import java.io.PrintWriter import java.util.concurrent.Executor import javax.inject.Inject -import javax.inject.Singleton /** * Provides information about the route (ie. device) where playback is occurring. */ -@Singleton class MediaDeviceManager @Inject constructor( private val context: Context, private val localMediaManagerFactory: LocalMediaManagerFactory, private val mr2manager: MediaRouter2Manager, @Main private val fgExecutor: Executor, @Background private val bgExecutor: Executor, - private val mediaDataManager: MediaDataManager, - private val dumpManager: DumpManager + dumpManager: DumpManager ) : MediaDataManager.Listener, Dumpable { + private val listeners: MutableSet<Listener> = mutableSetOf() private val entries: MutableMap<String, Entry> = mutableMapOf() init { - mediaDataManager.addListener(this) dumpManager.registerDumpable(javaClass.name, this) } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt index 70f01d576a9c..5475a00ced3c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt @@ -27,6 +27,7 @@ import android.view.View import android.view.ViewGroup import android.view.ViewGroupOverlay import com.android.systemui.Interpolators +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.NotificationLockscreenUserManager @@ -37,7 +38,6 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.animation.UniqueObjectHostView import javax.inject.Inject -import javax.inject.Singleton /** * Similarly to isShown but also excludes views that have 0 alpha @@ -65,7 +65,7 @@ val View.isShownNotFaded: Boolean * This manager is responsible for placement of the unique media view between the different hosts * and animate the positions of the views to achieve seamless transitions. */ -@Singleton +@SysUISingleton class MediaHierarchyManager @Inject constructor( private val context: Context, private val statusBarStateController: SysuiStatusBarStateController, @@ -389,6 +389,14 @@ class MediaHierarchyManager @Inject constructor( if (isCurrentlyInGuidedTransformation()) { return false } + // This is an invalid transition, and can happen when using the camera gesture from the + // lock screen. Disallow. + if (previousLocation == LOCATION_LOCKSCREEN && + desiredLocation == LOCATION_QQS && + statusbarState == StatusBarState.SHADE) { + return false + } + if (currentLocation == LOCATION_QQS && previousLocation == LOCATION_LOCKSCREEN && (statusBarStateController.leaveOpenOnKeyguardHide() || @@ -604,8 +612,8 @@ class MediaHierarchyManager @Inject constructor( // When collapsing on the lockscreen, we want to remain in QS return LOCATION_QS } - if (location != LOCATION_LOCKSCREEN && desiredLocation == LOCATION_LOCKSCREEN - && !fullyAwake) { + if (location != LOCATION_LOCKSCREEN && desiredLocation == LOCATION_LOCKSCREEN && + !fullyAwake) { // When unlocking from dozing / while waking up, the media shouldn't be transitioning // in an animated way. Let's keep it in the lockscreen until we're fully awake and // reattach it without an animation diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt index 3598719fcb3a..ce184aa23a57 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt @@ -14,7 +14,7 @@ import javax.inject.Inject class MediaHost @Inject constructor( private val state: MediaHostStateHolder, private val mediaHierarchyManager: MediaHierarchyManager, - private val mediaDataFilter: MediaDataFilter, + private val mediaDataManager: MediaDataManager, private val mediaHostStatesManager: MediaHostStatesManager ) : MediaHostState by state { lateinit var hostView: UniqueObjectHostView @@ -79,12 +79,12 @@ class MediaHost @Inject constructor( // be a delay until the views and the controllers are initialized, leaving us // with either a blank view or the controllers not yet initialized and the // measuring wrong - mediaDataFilter.addListener(listener) + mediaDataManager.addListener(listener) updateViewVisibility() } override fun onViewDetachedFromWindow(v: View?) { - mediaDataFilter.removeListener(listener) + mediaDataManager.removeListener(listener) } }) @@ -113,9 +113,9 @@ class MediaHost @Inject constructor( private fun updateViewVisibility() { visible = if (showsOnlyActiveMedia) { - mediaDataFilter.hasActiveMedia() + mediaDataManager.hasActiveMedia() } else { - mediaDataFilter.hasAnyMedia() + mediaDataManager.hasAnyMedia() } val newVisibility = if (visible) View.VISIBLE else View.GONE if (newVisibility != hostView.visibility) { @@ -289,4 +289,4 @@ interface MediaHostState { * Get a copy of this view state, deepcopying all appropriate members */ fun copy(): MediaHostState -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHostStatesManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHostStatesManager.kt index d3954b70ca71..ba7c1679b174 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHostStatesManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHostStatesManager.kt @@ -16,16 +16,16 @@ package com.android.systemui.media +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.util.animation.MeasurementOutput import javax.inject.Inject -import javax.inject.Singleton /** * A class responsible for managing all media host states of the various host locations and * coordinating the heights among different players. This class can be used to get the most up to * date state for any location. */ -@Singleton +@SysUISingleton class MediaHostStatesManager @Inject constructor() { private val callbacks: MutableSet<Callback> = mutableSetOf() diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt index c41712c4cf10..c00b5e92f93d 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt @@ -29,20 +29,20 @@ import android.provider.Settings import android.service.media.MediaBrowserService import android.util.Log import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.tuner.TunerService import com.android.systemui.util.Utils import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.Executor import javax.inject.Inject -import javax.inject.Singleton private const val TAG = "MediaResumeListener" private const val MEDIA_PREFERENCES = "media_control_prefs" private const val MEDIA_PREFERENCE_KEY = "browser_components_" -@Singleton +@SysUISingleton class MediaResumeListener @Inject constructor( private val context: Context, private val broadcastDispatcher: BroadcastDispatcher, diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt new file mode 100644 index 000000000000..f01713fb5f6c --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt @@ -0,0 +1,163 @@ +/* + * 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.media + +import android.content.ComponentName +import android.content.Context +import android.media.session.MediaController +import android.media.session.MediaController.PlaybackInfo +import android.media.session.MediaSession +import android.media.session.MediaSessionManager +import android.util.Log +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.statusbar.phone.NotificationListenerWithPlugins +import java.util.concurrent.Executor +import javax.inject.Inject + +private const val TAG = "MediaSessionBasedFilter" + +/** + * Filters media loaded events for local media sessions while an app is casting. + * + * When an app is casting there can be one remote media sessions and potentially more local media + * sessions. In this situation, there should only be a media object for the remote session. To + * achieve this, update events for the local session need to be filtered. + */ +class MediaSessionBasedFilter @Inject constructor( + context: Context, + private val sessionManager: MediaSessionManager, + @Main private val foregroundExecutor: Executor, + @Background private val backgroundExecutor: Executor +) : MediaDataManager.Listener { + + private val listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf() + + // Keep track of MediaControllers for a given package to check if an app is casting and it + // filter loaded events for local sessions. + private val packageControllers: LinkedHashMap<String, MutableList<MediaController>> = + LinkedHashMap() + + // Keep track of the key used for the session tokens. This information is used to know when + // dispatch a removed event so that a media object for a local session will be removed. + private val keyedTokens: MutableMap<String, MutableList<MediaSession.Token>> = mutableMapOf() + + private val sessionListener = object : MediaSessionManager.OnActiveSessionsChangedListener { + override fun onActiveSessionsChanged(controllers: List<MediaController>) { + handleControllersChanged(controllers) + } + } + + init { + backgroundExecutor.execute { + val name = ComponentName(context, NotificationListenerWithPlugins::class.java) + sessionManager.addOnActiveSessionsChangedListener(sessionListener, name) + handleControllersChanged(sessionManager.getActiveSessions(name)) + } + } + + /** + * Add a listener for filtered [MediaData] changes + */ + fun addListener(listener: MediaDataManager.Listener) = listeners.add(listener) + + /** + * Remove a listener that was registered with addListener + */ + fun removeListener(listener: MediaDataManager.Listener) = listeners.remove(listener) + + /** + * May filter loaded events by not passing them along to listeners. + * + * If an app has only one session with playback type PLAYBACK_TYPE_REMOTE, then assuming that + * the app is casting. Sometimes apps will send redundant updates to a local session with + * playback type PLAYBACK_TYPE_LOCAL. These updates should be filtered to improve the usability + * of the media controls. + */ + override fun onMediaDataLoaded(key: String, oldKey: String?, info: MediaData) { + backgroundExecutor.execute { + val isMigration = oldKey != null && key != oldKey + if (isMigration) { + keyedTokens.remove(oldKey)?.let { removed -> keyedTokens.put(key, removed) } + } + if (info.token != null) { + keyedTokens.get(key)?.let { + tokens -> + tokens.add(info.token) + } ?: run { + val tokens = mutableListOf(info.token) + keyedTokens.put(key, tokens) + } + } + // Determine if an app is casting by checking if it has a session with playback type + // PLAYBACK_TYPE_REMOTE. + val remoteControllers = packageControllers.get(info.packageName)?.filter { + it.playbackInfo?.playbackType == PlaybackInfo.PLAYBACK_TYPE_REMOTE + } + // Limiting search to only apps with a single remote session. + val remote = if (remoteControllers?.size == 1) remoteControllers.firstOrNull() else null + if (isMigration || remote == null || remote.sessionToken == info.token) { + // Not filtering in this case. Passing the event along to listeners. + dispatchMediaDataLoaded(key, oldKey, info) + } else { + // Filtering this event because the app is casting and the loaded events is for a + // local session. + Log.d(TAG, "filtering key=$key local=${info.token} remote=${remote?.sessionToken}") + // If the local session uses a different notification key, then lets go a step + // farther and dismiss the media data so that media controls for the local session + // don't hang around while casting. + if (!keyedTokens.get(key)!!.contains(remote.sessionToken)) { + dispatchMediaDataRemoved(key) + } + } + } + } + + override fun onMediaDataRemoved(key: String) { + // Queue on background thread to ensure ordering of loaded and removed events is maintained. + backgroundExecutor.execute { + keyedTokens.remove(key) + dispatchMediaDataRemoved(key) + } + } + + private fun dispatchMediaDataLoaded(key: String, oldKey: String?, info: MediaData) { + foregroundExecutor.execute { + listeners.toSet().forEach { it.onMediaDataLoaded(key, oldKey, info) } + } + } + + private fun dispatchMediaDataRemoved(key: String) { + foregroundExecutor.execute { + listeners.toSet().forEach { it.onMediaDataRemoved(key) } + } + } + + private fun handleControllersChanged(controllers: List<MediaController>) { + packageControllers.clear() + controllers.forEach { + controller -> + packageControllers.get(controller.packageName)?.let { + tokens -> + tokens.add(controller) + } ?: run { + val tokens = mutableListOf(controller) + packageControllers.put(controller.packageName, tokens) + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt index 8662aacfdab2..fdbff98ea831 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt @@ -20,12 +20,12 @@ import android.media.session.MediaController import android.media.session.PlaybackState import android.os.SystemProperties import android.util.Log +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState import com.android.systemui.util.concurrency.DelayableExecutor import java.util.concurrent.TimeUnit import javax.inject.Inject -import javax.inject.Singleton private const val DEBUG = true private const val TAG = "MediaTimeout" @@ -35,7 +35,7 @@ private val PAUSED_MEDIA_TIMEOUT = SystemProperties /** * Controller responsible for keeping track of playback states and expiring inactive streams. */ -@Singleton +@SysUISingleton class MediaTimeoutListener @Inject constructor( private val mediaControllerFactory: MediaControllerFactory, @Main private val mainExecutor: DelayableExecutor diff --git a/packages/SystemUI/src/com/android/systemui/model/SysUiState.java b/packages/SystemUI/src/com/android/systemui/model/SysUiState.java index ccf58ba5daa8..5dce09386c7d 100644 --- a/packages/SystemUI/src/com/android/systemui/model/SysUiState.java +++ b/packages/SystemUI/src/com/android/systemui/model/SysUiState.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.util.Log; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.shared.system.QuickStepContract; import java.io.FileDescriptor; @@ -29,13 +30,11 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; -import javax.inject.Singleton; - /** * Contains sysUi state flags and notifies registered * listeners whenever changes happen. */ -@Singleton +@SysUISingleton public class SysUiState implements Dumpable { private static final String TAG = SysUiState.class.getSimpleName(); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index 88400f0e0abe..6c8a23ba96d1 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -860,10 +860,13 @@ public class NavigationBar implements View.OnAttachStateChangeListener, final int barMode = barMode(mTransientShown, mAppearance); mNavigationBarMode = barMode; checkNavBarModes(); - mAutoHideController.touchAutoHide(); - - mLightBarController.onNavigationBarAppearanceChanged(mAppearance, true /* nbModeChanged */, - barMode, false /* navbarColorManagedByIme */); + if (mAutoHideController != null) { + mAutoHideController.touchAutoHide(); + } + if (mLightBarController != null) { + mLightBarController.onNavigationBarAppearanceChanged(mAppearance, + true /* nbModeChanged */, barMode, false /* navbarColorManagedByIme */); + } } @Override @@ -880,8 +883,10 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } nbModeChanged = updateBarMode(barMode(mTransientShown, appearance)); } - mLightBarController.onNavigationBarAppearanceChanged(appearance, nbModeChanged, - mNavigationBarMode, navbarColorManagedByIme); + if (mLightBarController != null) { + mLightBarController.onNavigationBarAppearanceChanged(appearance, nbModeChanged, + mNavigationBarMode, navbarColorManagedByIme); + } } @Override @@ -924,7 +929,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mNavigationBarView.onTransientStateChanged(mTransientShown); } final int barMode = barMode(mTransientShown, mAppearance); - if (updateBarMode(barMode)) { + if (updateBarMode(barMode) && mLightBarController != null) { mLightBarController.onNavigationBarModeChanged(barMode); } } @@ -938,7 +943,9 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } mNavigationBarMode = barMode; checkNavBarModes(); - mAutoHideController.touchAutoHide(); + if (mAutoHideController != null) { + mAutoHideController.touchAutoHide(); + } return true; } return false; @@ -1097,7 +1104,9 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } private boolean onNavigationTouch(View v, MotionEvent event) { - mAutoHideController.checkUserAutoHide(event); + if (mAutoHideController != null) { + mAutoHideController.checkUserAutoHide(event); + } return false; } @@ -1356,7 +1365,10 @@ public class NavigationBar implements View.OnAttachStateChangeListener, public void setLightBarController(LightBarController lightBarController) { mLightBarController = lightBarController; - mLightBarController.setNavigationBar(mNavigationBarView.getLightTransitionsController()); + if (mLightBarController != null) { + mLightBarController.setNavigationBar( + mNavigationBarView.getLightTransitionsController()); + } } /** Sets {@link AutoHideController} to the navigation bar. */ diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java index 73cdde8a0c91..fd157c632c7c 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java @@ -48,6 +48,7 @@ import com.android.systemui.accessibility.SystemActions; import com.android.systemui.assist.AssistHandleViewController; import com.android.systemui.assist.AssistManager; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -70,13 +71,12 @@ import java.io.PrintWriter; import java.util.Optional; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; /** A controller to handle navigation bars. */ -@Singleton +@SysUISingleton public class NavigationBarController implements Callbacks, ConfigurationController.ConfigurationListener, NavigationModeController.ModeChangedListener, Dumpable { diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java index 6e301c915af7..c704d32a4233 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java @@ -37,6 +37,7 @@ import android.provider.Settings.Secure; import android.util.Log; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -48,12 +49,11 @@ import java.util.ArrayList; import java.util.concurrent.Executor; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controller for tracking the current navigation bar mode. */ -@Singleton +@SysUISingleton public class NavigationModeController implements Dumpable { private static final String TAG = NavigationModeController.class.getSimpleName(); diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java index 2b07ac3f4d8a..9be1b5a35be6 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java @@ -19,6 +19,7 @@ package com.android.systemui.onehanded; import android.animation.Animator; import android.animation.ValueAnimator; import android.annotation.IntDef; +import android.content.Context; import android.graphics.Rect; import android.view.SurfaceControl; import android.view.animation.Interpolator; @@ -32,8 +33,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import javax.inject.Inject; - /** * Controller class of OneHanded animations (both from and to OneHanded mode). */ @@ -62,10 +61,8 @@ public class OneHandedAnimationController { /** * Constructor of OneHandedAnimationController */ - @Inject - public OneHandedAnimationController( - OneHandedSurfaceTransactionHelper surfaceTransactionHelper) { - mSurfaceTransactionHelper = surfaceTransactionHelper; + public OneHandedAnimationController(Context context) { + mSurfaceTransactionHelper = new OneHandedSurfaceTransactionHelper(context); mOvershootInterpolator = new OvershootInterpolator(); } diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java index 2e91697de849..ad9f7ea4e945 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java @@ -48,8 +48,6 @@ import java.util.HashMap; import java.util.List; import java.util.Objects; -import javax.inject.Inject; - /** * Manages OneHanded display areas such as offset. * @@ -149,7 +147,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen /** * Constructor of OneHandedDisplayAreaOrganizer */ - @Inject public OneHandedDisplayAreaOrganizer(Context context, DisplayController displayController, OneHandedAnimationController animationController, diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java index ba50db1c9f72..1420811b9b30 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java @@ -44,14 +44,10 @@ import com.android.systemui.navigationbar.NavigationModeController; import com.android.wm.shell.common.DisplayChangeController; import com.android.wm.shell.common.DisplayController; -import javax.inject.Inject; -import javax.inject.Singleton; - /** * The class manage swipe up and down gesture for 3-Button mode navigation, * others(e.g, 2-button, full gesture mode) are handled by Launcher quick steps. */ -@Singleton public class OneHandedGestureHandler implements OneHandedTransitionCallback, NavigationModeController.ModeChangedListener, DisplayChangeController.OnDisplayChangingListener { @@ -91,7 +87,6 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback, * @param displayController {@link DisplayController} * @param navigationModeController {@link NavigationModeController} */ - @Inject public OneHandedGestureHandler(Context context, DisplayController displayController, NavigationModeController navigationModeController) { mDisplayController = displayController; diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java index 42524bb33818..90e7e12b2b47 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java @@ -31,7 +31,9 @@ import androidx.annotation.NonNull; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.model.SysUiState; +import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.statusbar.CommandQueue; @@ -42,12 +44,11 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import javax.inject.Inject; -import javax.inject.Singleton; /** * Manages and manipulates the one handed states, transitions, and gesture for phones. */ -@Singleton +@SysUISingleton public class OneHandedManagerImpl implements OneHandedManager, Dumpable { private static final String TAG = "OneHandedManager"; private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE = @@ -94,7 +95,6 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable { /** * Handle rotation based on OnDisplayChangingListener callback */ - @VisibleForTesting private final DisplayChangeController.OnDisplayChangingListener mRotationController = (display, fromRotation, toRotation, wct) -> { if (mDisplayAreaOrganizer != null) { @@ -109,6 +109,37 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable { public OneHandedManagerImpl(Context context, CommandQueue commandQueue, DisplayController displayController, + NavigationModeController navigationModeController, + SysUiState sysUiState) { + mCommandQueue = commandQueue; + mDisplayController = displayController; + mDisplayController.addDisplayChangingController(mRotationController); + mSysUiFlagContainer = sysUiState; + mOffSetFraction = SystemProperties.getInt(ONE_HANDED_MODE_OFFSET_PERCENTAGE, 50) / 100.0f; + + mIsOneHandedEnabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled( + context.getContentResolver()); + mIsSwipeToNotificationEnabled = OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled( + context.getContentResolver()); + mTimeoutHandler = OneHandedTimeoutHandler.get(); + mTouchHandler = new OneHandedTouchHandler(); + mTutorialHandler = new OneHandedTutorialHandler(context); + mDisplayAreaOrganizer = new OneHandedDisplayAreaOrganizer(context, displayController, + new OneHandedAnimationController(context), mTutorialHandler); + mGestureHandler = new OneHandedGestureHandler( + context, displayController, navigationModeController); + updateOneHandedEnabled(); + setupGestures(); + } + + /** + * Constructor of OneHandedManager for testing + */ + // TODO(b/161980408): Should remove extra constructor. + @VisibleForTesting + OneHandedManagerImpl(Context context, + CommandQueue commandQueue, + DisplayController displayController, OneHandedDisplayAreaOrganizer displayAreaOrganizer, OneHandedTouchHandler touchHandler, OneHandedTutorialHandler tutorialHandler, diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSettingsUtil.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSettingsUtil.java index 1b6ec04193f0..0598f32c16d5 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSettingsUtil.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSettingsUtil.java @@ -22,19 +22,16 @@ import android.database.ContentObserver; import android.net.Uri; import android.provider.Settings; -import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.dagger.SysUISingleton; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import javax.inject.Inject; -import javax.inject.Singleton; - /** * APIs for querying or updating one handed settings . */ -@Singleton +@SysUISingleton public final class OneHandedSettingsUtil { private static final String TAG = "OneHandedSettingsUtil"; @@ -65,11 +62,6 @@ public final class OneHandedSettingsUtil { */ public static final int ONE_HANDED_TIMEOUT_LONG_IN_SECONDS = 12; - @VisibleForTesting - @Inject - OneHandedSettingsUtil() { - } - /** * Register one handed preference settings observer * @@ -150,4 +142,6 @@ public final class OneHandedSettingsUtil { pw.print(innerPrefix + "tapsAppToExit="); pw.println(getSettingsTapsAppToExit(resolver)); } + + private OneHandedSettingsUtil() {} } diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSurfaceTransactionHelper.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSurfaceTransactionHelper.java index 5933eb333bf3..bc4a9b49205c 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSurfaceTransactionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSurfaceTransactionHelper.java @@ -23,8 +23,6 @@ import android.view.SurfaceControl; import com.android.systemui.R; -import javax.inject.Inject; - /** * Abstracts the common operations on {@link SurfaceControl.Transaction} for OneHanded transition. */ @@ -32,7 +30,6 @@ public class OneHandedSurfaceTransactionHelper { private final boolean mEnableCornerRadius; private final float mCornerRadius; - @Inject public OneHandedSurfaceTransactionHelper(Context context) { final Resources res = context.getResources(); mCornerRadius = res.getDimension(com.android.internal.R.dimen.rounded_corner_radius); diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java index 194b24f95458..6bed30425c55 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java @@ -33,12 +33,9 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; -import javax.inject.Singleton; - /** * Timeout handler for stop one handed mode operations. */ -@Singleton public class OneHandedTimeoutHandler implements Dumpable { private static final String TAG = "OneHandedTimeoutHandler"; private static boolean sIsDragging = false; diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java index 1446e5a431c6..0a7eb1bdada0 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java @@ -35,15 +35,11 @@ import com.android.systemui.Dumpable; import java.io.FileDescriptor; import java.io.PrintWriter; -import javax.inject.Inject; -import javax.inject.Singleton; - /** * Manages all the touch handling for One Handed on the Phone, including user tap outside region * to exit, reset timer when user is in one-handed mode. * Refer {@link OneHandedGestureHandler} to see start and stop one handed gesture */ -@Singleton public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpable { private static final String TAG = "OneHandedTouchHandler"; private final Rect mLastUpdatedBounds = new Rect(); @@ -61,7 +57,6 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpa private boolean mIsOnStopTransitioning; private boolean mIsInOutsideRegion; - @Inject public OneHandedTouchHandler() { mTimeoutHandler = OneHandedTimeoutHandler.get(); updateIsEnabled(); diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java index de34b2ec831d..8ef9b092bc00 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java @@ -39,16 +39,12 @@ import com.android.systemui.R; import java.io.FileDescriptor; import java.io.PrintWriter; -import javax.inject.Inject; -import javax.inject.Singleton; - /** * Manages the user tutorial handling for One Handed operations, including animations synchronized * with one-handed translation. * Refer {@link OneHandedGestureHandler} and {@link OneHandedTouchHandler} to see start and stop * one handed gesture */ -@Singleton public class OneHandedTutorialHandler implements OneHandedTransitionCallback, Dumpable { private static final String TAG = "OneHandedTutorialHandler"; private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE = @@ -76,7 +72,6 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback, Du } }; - @Inject public OneHandedTutorialHandler(Context context) { context.getDisplay().getRealSize(mDisplaySize); mContentResolver = context.getContentResolver(); diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java index 0903c0e5c512..cebcd4ceabe9 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java @@ -40,6 +40,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.Dependency; import com.android.systemui.Dumpable; import com.android.systemui.SystemUI; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.statusbar.CommandQueue; @@ -47,12 +48,11 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import javax.inject.Inject; -import javax.inject.Singleton; /** * A service that controls UI of the one handed mode function. */ -@Singleton +@SysUISingleton public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dumpable { private static final String TAG = "OneHandedUI"; private static final String ONE_HANDED_MODE_GESTURAL_OVERLAY = @@ -63,7 +63,6 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum private final CommandQueue mCommandQueue; private final Handler mMainHandler = new Handler(Looper.getMainLooper()); private final IOverlayManager mOverlayManager; - private final OneHandedSettingsUtil mSettingUtil; private final OneHandedTimeoutHandler mTimeoutHandler; private final ScreenLifecycle mScreenLifecycle; @@ -154,7 +153,6 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum public OneHandedUI(Context context, CommandQueue commandQueue, OneHandedManagerImpl oneHandedManager, - OneHandedSettingsUtil settingsUtil, ScreenLifecycle screenLifecycle) { super(context); @@ -163,7 +161,6 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum mCommandQueue = null; mOneHandedManager = null; mOverlayManager = null; - mSettingUtil = null; mTimeoutHandler = null; mScreenLifecycle = null; return; @@ -171,7 +168,6 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum mCommandQueue = commandQueue; mOneHandedManager = oneHandedManager; - mSettingUtil = settingsUtil; mTimeoutHandler = OneHandedTimeoutHandler.get(); mScreenLifecycle = screenLifecycle; mOverlayManager = IOverlayManager.Stub.asInterface( @@ -252,26 +248,26 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum } private void setupSettingObservers() { - mSettingUtil.registerSettingsKeyObserver(Settings.Secure.ONE_HANDED_MODE_ENABLED, + OneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.ONE_HANDED_MODE_ENABLED, mContext.getContentResolver(), mEnabledObserver); - mSettingUtil.registerSettingsKeyObserver(Settings.Secure.ONE_HANDED_MODE_TIMEOUT, + OneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.ONE_HANDED_MODE_TIMEOUT, mContext.getContentResolver(), mTimeoutObserver); - mSettingUtil.registerSettingsKeyObserver(Settings.Secure.TAPS_APP_TO_EXIT, + OneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.TAPS_APP_TO_EXIT, mContext.getContentResolver(), mTaskChangeExitObserver); - mSettingUtil.registerSettingsKeyObserver( + OneHandedSettingsUtil.registerSettingsKeyObserver( Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, mContext.getContentResolver(), mSwipeToNotificationEnabledObserver); } private void updateSettings() { - mOneHandedManager.setOneHandedEnabled( - mSettingUtil.getSettingsOneHandedModeEnabled(mContext.getContentResolver())); - mTimeoutHandler.setTimeout( - mSettingUtil.getSettingsOneHandedModeTimeout(mContext.getContentResolver())); - mOneHandedManager.setTaskChangeToExit( - mSettingUtil.getSettingsTapsAppToExit(mContext.getContentResolver())); - mOneHandedManager.setSwipeToNotificationEnabled( - mSettingUtil.getSettingsSwipeToNotificationEnabled(mContext.getContentResolver())); + mOneHandedManager.setOneHandedEnabled(OneHandedSettingsUtil + .getSettingsOneHandedModeEnabled(mContext.getContentResolver())); + mTimeoutHandler.setTimeout(OneHandedSettingsUtil + .getSettingsOneHandedModeTimeout(mContext.getContentResolver())); + mOneHandedManager.setTaskChangeToExit(OneHandedSettingsUtil + .getSettingsTapsAppToExit(mContext.getContentResolver())); + mOneHandedManager.setSwipeToNotificationEnabled(OneHandedSettingsUtil + .getSettingsSwipeToNotificationEnabled(mContext.getContentResolver())); } @Override @@ -326,9 +322,7 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum mTimeoutHandler.dump(fd, pw, args); } - if (mSettingUtil != null) { - mSettingUtil.dump(pw, innerPrefix, mContext.getContentResolver()); - } + OneHandedSettingsUtil.dump(pw, innerPrefix, mContext.getContentResolver()); if (mOverlayManager != null) { OverlayInfo info = null; diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java index df3aeadaacd6..d6aa61b0c767 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java @@ -39,19 +39,19 @@ import android.view.DisplayInfo; import android.view.Gravity; import android.window.WindowContainerTransaction; +import com.android.systemui.dagger.SysUISingleton; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayLayout; import java.io.PrintWriter; import javax.inject.Inject; -import javax.inject.Singleton; /** * Handles bounds calculation for PIP on Phone and other form factors, it keeps tracking variant * state changes originated from Window Manager and is the source of truth for PiP window bounds. */ -@Singleton +@SysUISingleton public class PipBoundsHandler { private static final String TAG = PipBoundsHandler.class.getSimpleName(); diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipSurfaceTransactionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/PipSurfaceTransactionHelper.java index 2c7ec48e4ae7..e88451ca00b5 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipSurfaceTransactionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipSurfaceTransactionHelper.java @@ -23,16 +23,16 @@ import android.graphics.Rect; import android.graphics.RectF; import android.view.SurfaceControl; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.wm.shell.R; import javax.inject.Inject; -import javax.inject.Singleton; /** * Abstracts the common operations on {@link SurfaceControl.Transaction} for PiP transition. */ -@Singleton +@SysUISingleton public class PipSurfaceTransactionHelper implements ConfigurationController.ConfigurationListener { private final Context mContext; diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index 025341cf4fba..0e60c83b8392 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java @@ -56,6 +56,7 @@ import android.window.WindowContainerTransactionCallback; import android.window.WindowOrganizer; import com.android.internal.os.SomeArgs; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.pip.phone.PipUpdateThread; import com.android.systemui.stackdivider.Divider; import com.android.wm.shell.R; @@ -70,7 +71,6 @@ import java.util.Objects; import java.util.function.Consumer; import javax.inject.Inject; -import javax.inject.Singleton; /** * Manages PiP tasks such as resize and offset. @@ -83,7 +83,7 @@ import javax.inject.Singleton; * This class is also responsible for general resize/offset PiP operations within SysUI component, * see also {@link com.android.systemui.pip.phone.PipMotionHelper}. */ -@Singleton +@SysUISingleton public class PipTaskOrganizer extends TaskOrganizer implements DisplayController.OnDisplaysChangedListener { private static final String TAG = PipTaskOrganizer.class.getSimpleName(); diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java index 4fb675e31f0e..2cd1e202125d 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java @@ -25,6 +25,7 @@ import android.os.UserHandle; import android.os.UserManager; import com.android.systemui.SystemUI; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.shared.recents.IPinnedStackAnimationListener; import com.android.systemui.statusbar.CommandQueue; @@ -32,12 +33,11 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controls the picture-in-picture window. */ -@Singleton +@SysUISingleton public class PipUI extends SystemUI implements CommandQueue.Callbacks { private final CommandQueue mCommandQueue; diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipUiEventLogger.java b/packages/SystemUI/src/com/android/systemui/pip/PipUiEventLogger.java index 5e2cd9c111b2..7ce2028b5f1b 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipUiEventLogger.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipUiEventLogger.java @@ -20,15 +20,15 @@ import android.app.TaskInfo; import com.android.internal.logging.UiEvent; import com.android.internal.logging.UiEventLogger; +import com.android.systemui.dagger.SysUISingleton; import javax.inject.Inject; -import javax.inject.Singleton; /** * Helper class that ends PiP log to UiEvent, see also go/uievent */ -@Singleton +@SysUISingleton public class PipUiEventLogger { private final UiEventLogger mUiEventLogger; diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index d96f7dde0dff..facb3966f78c 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -42,6 +42,7 @@ import android.window.WindowContainerTransaction; import com.android.systemui.Dependency; import com.android.systemui.UiOffloadThread; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.model.SysUiState; import com.android.systemui.pip.BasePipManager; import com.android.systemui.pip.PipBoundsHandler; @@ -64,12 +65,11 @@ import com.android.wm.shell.common.DisplayController; import java.io.PrintWriter; import javax.inject.Inject; -import javax.inject.Singleton; /** * Manages the picture-in-picture (PIP) UI and states for Phones. */ -@Singleton +@SysUISingleton public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitionCallback { private static final String TAG = "PipManager"; 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 f1c8b0cf0e42..74dc003bd8b6 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java @@ -49,6 +49,7 @@ import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.UiOffloadThread; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.pip.BasePipManager; import com.android.systemui.pip.PipBoundsHandler; import com.android.systemui.pip.PipSurfaceTransactionHelper; @@ -63,12 +64,11 @@ import java.util.ArrayList; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * Manages the picture-in-picture (PIP) UI and states. */ -@Singleton +@SysUISingleton public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitionCallback { private static final String TAG = "PipManager"; static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java index 69495319e060..ad1e21d7cc45 100644 --- a/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java +++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java @@ -17,15 +17,15 @@ package com.android.systemui.plugins; import android.util.ArrayMap; import com.android.systemui.Dependency; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.PluginDependency.DependencyProvider; import com.android.systemui.shared.plugins.PluginManager; import javax.inject.Inject; -import javax.inject.Singleton; /** */ -@Singleton +@SysUISingleton public class PluginDependencyProvider extends DependencyProvider { private final ArrayMap<Class<?>, Object> mDependencies = new ArrayMap<>(); diff --git a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java index 7d54c211242f..90da8912ad75 100644 --- a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java @@ -2,11 +2,11 @@ package com.android.systemui.power; import com.android.settingslib.fuelgauge.Estimate; import com.android.settingslib.fuelgauge.EstimateKt; +import com.android.systemui.dagger.SysUISingleton; import javax.inject.Inject; -import javax.inject.Singleton; -@Singleton +@SysUISingleton public class EnhancedEstimatesImpl implements EnhancedEstimates { @Inject diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java index 6abbbbeaa397..a27e9ac61848 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java @@ -59,6 +59,7 @@ import com.android.settingslib.utils.PowerUtil; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SystemUI; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.util.NotificationChannels; @@ -70,11 +71,10 @@ import java.util.Locale; import java.util.Objects; import javax.inject.Inject; -import javax.inject.Singleton; /** */ -@Singleton +@SysUISingleton public class PowerNotificationWarnings implements PowerUI.WarningsUI { private static final String TAG = PowerUI.TAG + ".Notification"; diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java index 66804bef8f53..a888305cc83d 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java @@ -46,6 +46,7 @@ import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SystemUI; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.StatusBar; @@ -56,11 +57,10 @@ import java.util.Arrays; import java.util.concurrent.Future; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; -@Singleton +@SysUISingleton public class PowerUI extends SystemUI implements CommandQueue.Callbacks { static final String TAG = "PowerUI"; diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt index affc5ee1fdf0..255ba1b61db1 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt @@ -31,6 +31,7 @@ import com.android.systemui.Dumpable import com.android.systemui.appops.AppOpItem import com.android.systemui.appops.AppOpsController import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dump.DumpManager @@ -41,9 +42,8 @@ import java.io.PrintWriter import java.lang.ref.WeakReference import java.util.concurrent.Executor import javax.inject.Inject -import javax.inject.Singleton -@Singleton +@SysUISingleton class PrivacyItemController @Inject constructor( private val appOpsController: AppOpsController, @Main uiExecutor: DelayableExecutor, diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java index 3b16a4ec1c38..9a63a56b2c8e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java @@ -37,6 +37,7 @@ import com.android.internal.logging.UiEventLogger; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; @@ -69,10 +70,9 @@ import java.util.function.Predicate; import javax.inject.Inject; import javax.inject.Provider; -import javax.inject.Singleton; /** Platform implementation of the quick settings tile host **/ -@Singleton +@SysUISingleton public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, Dumpable { private static final String TAG = "QSTileHost"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java index 69a6fe1075c2..8e33496e73af 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java @@ -20,6 +20,7 @@ import android.util.Log; import android.view.ContextThemeWrapper; import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.qs.QSFactory; import com.android.systemui.plugins.qs.QSIconView; import com.android.systemui.plugins.qs.QSTile; @@ -49,11 +50,10 @@ import com.android.systemui.util.leak.GarbageMonitor; import javax.inject.Inject; import javax.inject.Provider; -import javax.inject.Singleton; import dagger.Lazy; -@Singleton +@SysUISingleton public class QSFactoryImpl implements QSFactory { private static final String TAG = "QSFactory"; diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java index f89185e3efa9..0347867b61fc 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java @@ -35,6 +35,7 @@ import android.widget.Toast; import com.android.systemui.Dependency; import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.stackdivider.Divider; @@ -43,14 +44,13 @@ import com.android.systemui.statusbar.phone.StatusBar; import java.util.Optional; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; /** * An implementation of the Recents interface which proxies to the OverviewProxyService. */ -@Singleton +@SysUISingleton public class OverviewProxyRecentsImpl implements RecentsImplementation { private final static String TAG = "OverviewProxyRecentsImpl"; diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index 5fb71e8b773e..e931a6bf179a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -61,12 +61,19 @@ import android.view.MotionEvent; import android.view.Surface; import android.view.accessibility.AccessibilityManager; +import androidx.annotation.NonNull; + import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity; import com.android.internal.policy.ScreenDecorationsUtils; import com.android.internal.util.ScreenshotHelper; import com.android.systemui.Dumpable; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.model.SysUiState; +import com.android.systemui.navigationbar.NavigationBar; +import com.android.systemui.navigationbar.NavigationBarController; +import com.android.systemui.navigationbar.NavigationBarView; +import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.onehanded.OneHandedUI; import com.android.systemui.pip.PipAnimationController; import com.android.systemui.pip.PipUI; @@ -81,11 +88,7 @@ import com.android.systemui.shared.system.InputMonitorCompat; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.stackdivider.Divider; import com.android.systemui.statusbar.CommandQueue; -import com.android.systemui.navigationbar.NavigationBarController; -import com.android.systemui.navigationbar.NavigationBar; -import com.android.systemui.navigationbar.NavigationBarView; -import com.android.systemui.navigationbar.NavigationModeController; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarWindowCallback; import com.android.systemui.statusbar.policy.CallbackController; @@ -97,14 +100,13 @@ import java.util.List; import java.util.Optional; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; /** * Class to send information from overview to launcher with a binder. */ -@Singleton +@SysUISingleton public class OverviewProxyService extends CurrentUserTracker implements CallbackController<OverviewProxyListener>, NavigationModeController.ModeChangedListener, Dumpable { @@ -808,7 +810,7 @@ public class OverviewProxyService extends CurrentUserTracker implements } @Override - public void addCallback(OverviewProxyListener listener) { + public void addCallback(@NonNull OverviewProxyListener listener) { if (!mConnectionCallbacks.contains(listener)) { mConnectionCallbacks.add(listener); } @@ -817,7 +819,7 @@ public class OverviewProxyService extends CurrentUserTracker implements } @Override - public void removeCallback(OverviewProxyListener listener) { + public void removeCallback(@NonNull OverviewProxyListener listener) { mConnectionCallbacks.remove(listener); } diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java index 82ac1f6f6a33..10a44ddb17f2 100644 --- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java +++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java @@ -26,19 +26,21 @@ import android.os.CountDownTimer; import android.os.UserHandle; import android.util.Log; +import androidx.annotation.NonNull; + import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.policy.CallbackController; import java.util.ArrayList; import javax.inject.Inject; -import javax.inject.Singleton; /** * Helper class to initiate a screen recording */ -@Singleton +@SysUISingleton public class RecordingController implements CallbackController<RecordingController.RecordingStateChangeCallback> { private static final String TAG = "RecordingController"; @@ -191,12 +193,12 @@ public class RecordingController } @Override - public void addCallback(RecordingStateChangeCallback listener) { + public void addCallback(@NonNull RecordingStateChangeCallback listener) { mListeners.add(listener); } @Override - public void removeCallback(RecordingStateChangeCallback listener) { + public void removeCallback(@NonNull RecordingStateChangeCallback listener) { mListeners.remove(listener); } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java index 6747281ac437..e24fbc6cca9d 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java @@ -81,6 +81,7 @@ import android.widget.Toast; import com.android.internal.logging.UiEventLogger; import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.shared.system.QuickStepContract; @@ -89,12 +90,11 @@ import java.util.List; import java.util.function.Consumer; import javax.inject.Inject; -import javax.inject.Singleton; /** * Class for handling device screen shots */ -@Singleton +@SysUISingleton public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInsetsListener { /** diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java index b5209bbbdd21..a48870240384 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java @@ -65,10 +65,10 @@ public class ScreenshotActionChip extends FrameLayout { } void setIcon(Icon icon, boolean tint) { - if (tint) { - icon.setTint(mIconColor); - } mIcon.setImageIcon(icon); + if (!tint) { + mIcon.setImageTintList(null); + } } void setText(CharSequence text) { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java index 633cdd6ca5ca..468602a5369e 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java @@ -31,6 +31,7 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.SystemUIFactory; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.shared.system.ActivityManagerWrapper; import java.util.Collections; @@ -40,12 +41,11 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import javax.inject.Inject; -import javax.inject.Singleton; /** * Collects the static functions for retrieving and acting on smart actions. */ -@Singleton +@SysUISingleton public class ScreenshotSmartActions { private static final String TAG = "ScreenshotSmartActions"; diff --git a/packages/SystemUI/src/com/android/systemui/settings/dagger/SettingsModule.java b/packages/SystemUI/src/com/android/systemui/settings/dagger/SettingsModule.java index eb5bd5c01a78..b1ed77275187 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/dagger/SettingsModule.java +++ b/packages/SystemUI/src/com/android/systemui/settings/dagger/SettingsModule.java @@ -19,11 +19,10 @@ package com.android.systemui.settings.dagger; import android.content.Context; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.settings.CurrentUserContentResolverProvider; import com.android.systemui.settings.CurrentUserContextTracker; -import javax.inject.Singleton; - import dagger.Binds; import dagger.Module; import dagger.Provides; @@ -37,7 +36,7 @@ public abstract class SettingsModule { /** * Provides and initializes a CurrentUserContextTracker */ - @Singleton + @SysUISingleton @Provides static CurrentUserContextTracker provideCurrentUserContextTracker( Context context, @@ -49,7 +48,7 @@ public abstract class SettingsModule { } @Binds - @Singleton + @SysUISingleton abstract CurrentUserContentResolverProvider bindCurrentUserContentResolverTracker( CurrentUserContextTracker tracker); } diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java index f7f12239c6db..ee3303bf33ef 100644 --- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java +++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java @@ -28,17 +28,17 @@ import android.view.WindowManagerGlobal; import com.android.internal.policy.DividerSnapAlgorithm; import com.android.systemui.SystemUI; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.recents.Recents; import com.android.systemui.stackdivider.Divider; import com.android.systemui.stackdivider.DividerView; import javax.inject.Inject; -import javax.inject.Singleton; /** * Dispatches shortcut to System UI components */ -@Singleton +@SysUISingleton public class ShortcutKeyDispatcher extends SystemUI implements ShortcutKeyServiceProxy.Callbacks { diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index d40b666860e9..e9c880ebbcc9 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -23,6 +23,7 @@ import android.content.Context; import android.window.WindowContainerToken; import com.android.systemui.SystemUI; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -31,12 +32,10 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.function.Consumer; -import javax.inject.Singleton; - /** * Controls the docked stack divider. */ -@Singleton +@SysUISingleton public class Divider extends SystemUI { private final KeyguardStateController mKeyguardStateController; private final DividerController mDividerController; diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java index db0aef8a0611..9c2139772e7d 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java @@ -19,6 +19,7 @@ package com.android.systemui.stackdivider; import android.content.Context; import android.os.Handler; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.wm.shell.common.DisplayController; @@ -26,8 +27,6 @@ import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.common.TransactionPool; -import javax.inject.Singleton; - import dagger.Module; import dagger.Provides; @@ -36,7 +35,7 @@ import dagger.Provides; */ @Module public class DividerModule { - @Singleton + @SysUISingleton @Provides static Divider provideDivider(Context context, DisplayController displayController, SystemWindows systemWindows, DisplayImeController imeController, @Main Handler handler, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt index c70d3847bd6f..f758db8a6ba4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt @@ -26,14 +26,14 @@ import androidx.annotation.VisibleForTesting import com.android.internal.util.IndentingPrintWriter import com.android.systemui.Dumpable import com.android.systemui.R +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dump.DumpManager import java.io.FileDescriptor import java.io.PrintWriter import javax.inject.Inject -import javax.inject.Singleton -@Singleton +@SysUISingleton open class BlurUtils @Inject constructor( @Main private val resources: Resources, dumpManager: DumpManager diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 1638dd9664a4..4673ec73c25a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -49,6 +49,8 @@ import android.util.SparseArray; import android.view.InsetsState.InternalInsetsType; import android.view.WindowInsetsController.Appearance; +import androidx.annotation.NonNull; + import com.android.internal.os.SomeArgs; import com.android.internal.statusbar.IStatusBar; import com.android.internal.statusbar.StatusBarIcon; @@ -391,7 +393,8 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< && !ONLY_CORE_APPS; } - public void addCallback(Callbacks callbacks) { + @Override + public void addCallback(@NonNull Callbacks callbacks) { mCallbacks.add(callbacks); // TODO(b/117478341): find a better way to pass disable flags by display. for (int i = 0; i < mDisplayDisabled.size(); i++) { @@ -402,7 +405,8 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< } } - public void removeCallback(Callbacks callbacks) { + @Override + public void removeCallback(@NonNull Callbacks callbacks) { mCallbacks.remove(callbacks); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java index 6839921e90a7..3811ca929f6e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java @@ -20,13 +20,13 @@ import android.annotation.NonNull; import android.provider.DeviceConfig; import android.util.ArrayMap; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import java.util.Map; import java.util.concurrent.Executor; import javax.inject.Inject; -import javax.inject.Singleton; /** * Class to manage simple DeviceConfig-based feature flags. @@ -43,7 +43,7 @@ import javax.inject.Singleton; * $ adb shell am restart com.android.systemui * } */ -@Singleton +@SysUISingleton public class FeatureFlags { private final Map<String, Boolean> mCachedDeviceConfigFlags = new ArrayMap<>(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 7e1dc6634cec..a59ff38896dc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -55,6 +55,7 @@ import com.android.settingslib.fuelgauge.BatteryStatus; import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dock.DockManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; @@ -71,12 +72,11 @@ import java.text.NumberFormat; import java.util.IllegalFormatConversionException; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controls the indications and error messages shown on the Keyguard */ -@Singleton +@SysUISingleton public class KeyguardIndicationController implements StateListener, KeyguardStateController.Callback { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt index 326757e9a4c1..750272d65659 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt @@ -28,17 +28,16 @@ import android.renderscript.ScriptIntrinsicBlur import android.util.Log import android.util.MathUtils import com.android.internal.graphics.ColorUtils +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.notification.MediaNotificationProcessor - import javax.inject.Inject -import javax.inject.Singleton private const val TAG = "MediaArtworkProcessor" private const val COLOR_ALPHA = (255 * 0.7f).toInt() private const val BLUR_RADIUS = 25f private const val DOWNSAMPLE = 6 -@Singleton +@SysUISingleton class MediaArtworkProcessor @Inject constructor() { private val mTmpSize = Point() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt index 8248fc9f5844..abf81c5c4cb6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt @@ -4,11 +4,11 @@ import android.app.Notification import android.os.RemoteException import com.android.internal.statusbar.IStatusBarService import com.android.internal.statusbar.NotificationVisibility +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.util.Assert import java.util.concurrent.Executor import javax.inject.Inject -import javax.inject.Singleton /** * Class to shim calls to IStatusBarManager#onNotificationClick/#onNotificationActionClick that @@ -18,7 +18,7 @@ import javax.inject.Singleton * NOTE: this class eats exceptions from system server, as no current client of these APIs cares * about errors */ -@Singleton +@SysUISingleton public class NotificationClickNotifier @Inject constructor( val barService: IStatusBarService, @Main val mainExecutor: Executor diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt index 9dbec1037aa5..2ca1bebfcf9f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt @@ -1,16 +1,16 @@ package com.android.systemui.statusbar +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.notification.NotificationEntryManager import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener import javax.inject.Inject -import javax.inject.Singleton /** * Class to track user interaction with notifications. It's a glorified map of key : bool that can * merge multiple "user interacted with notification" signals into a single place. */ -@Singleton +@SysUISingleton class NotificationInteractionTracker @Inject constructor( private val clicker: NotificationClickNotifier, private val entryManager: NotificationEntryManager diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java index 03424c4956ad..8d82270c9ca7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java @@ -48,6 +48,7 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.Dependency; import com.android.systemui.Dumpable; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; @@ -65,13 +66,12 @@ import java.util.ArrayList; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * Handles keeping track of the current user, profiles, and various things related to hiding * contents, redacting notifications, and the lockscreen. */ -@Singleton +@SysUISingleton public class NotificationLockscreenUserManagerImpl implements Dumpable, NotificationLockscreenUserManager, StateListener { private static final String TAG = "LockscreenUserManager"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java index 739d30c2a707..c01bdc4c2f28 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java @@ -60,7 +60,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.LockscreenWallpaper; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ScrimState; import com.android.systemui.statusbar.phone.StatusBar; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt index 0445c9879ac5..c1196d65b702 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt @@ -32,27 +32,26 @@ import androidx.dynamicanimation.animation.SpringForce import com.android.internal.util.IndentingPrintWriter import com.android.systemui.Dumpable import com.android.systemui.Interpolators +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.notification.ActivityLaunchAnimator import com.android.systemui.statusbar.phone.BiometricUnlockController import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK import com.android.systemui.statusbar.phone.DozeParameters -import com.android.systemui.statusbar.phone.NotificationShadeWindowController import com.android.systemui.statusbar.phone.PanelExpansionListener import com.android.systemui.statusbar.phone.ScrimController import com.android.systemui.statusbar.policy.KeyguardStateController import java.io.FileDescriptor import java.io.PrintWriter import javax.inject.Inject -import javax.inject.Singleton import kotlin.math.max import kotlin.math.sign /** * Controller responsible for statusbar window blur. */ -@Singleton +@SysUISingleton class NotificationShadeDepthController @Inject constructor( private val statusBarStateController: StatusBarStateController, private val blurUtils: BlurUtils, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java new file mode 100644 index 000000000000..1fd0b03a77b7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java @@ -0,0 +1,184 @@ +/* + * 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.ViewGroup; + +import androidx.annotation.Nullable; + +import com.android.systemui.statusbar.phone.StatusBarWindowCallback; + +import java.util.function.Consumer; + +/** + * Interface to control the state of the notification shade window. Not all methods of this + * interface will be used by each implementation of {@link NotificationShadeWindowController}. + */ +public interface NotificationShadeWindowController extends RemoteInputController.Callback { + + /** + * Registers a {@link StatusBarWindowCallback} to receive notifications about status bar + * window state changes. + */ + default void registerCallback(StatusBarWindowCallback callback) {} + + /** Notifies the registered {@link StatusBarWindowCallback} instances. */ + default void notifyStateChangedCallbacks() {} + + /** + * Registers a listener to monitor scrims visibility. + * + * @param listener A listener to monitor scrims visibility + */ + default void setScrimsVisibilityListener(Consumer<Integer> listener) {} + + /** + * Adds the notification shade view to the window manager. + */ + default void attach() {} + + /** Sets the notification shade view. */ + default void setNotificationShadeView(ViewGroup view) {} + + /** Gets the notification shade view. */ + @Nullable + default ViewGroup getNotificationShadeView() { + return null; + } + + /** Sets the state of whether the keyguard is currently showing or not. */ + default void setKeyguardShowing(boolean showing) {} + + /** Sets the state of whether the keyguard is currently occluded or not. */ + default void setKeyguardOccluded(boolean occluded) {} + + /** Sets the state of whether the keyguard is currently needs input or not. */ + default void setKeyguardNeedsInput(boolean needsInput) {} + + /** Sets the state of whether the notification shade panel is currently visible or not. */ + default void setPanelVisible(boolean visible) {} + + /** Sets the state of whether the notification shade is focusable or not. */ + default void setNotificationShadeFocusable(boolean focusable) {} + + /** Sets the state of whether the bouncer is showing or not. */ + default void setBouncerShowing(boolean showing) {} + + /** Sets the state of whether the backdrop is showing or not. */ + default void setBackdropShowing(boolean showing) {} + + /** Sets the state of whether the keyguard is fading away or not. */ + default void setKeyguardFadingAway(boolean keyguardFadingAway) {} + + /** Sets the state of whether the quick settings is expanded or not. */ + default void setQsExpanded(boolean expanded) {} + + /** Sets the state of whether the user activities are forced or not. */ + default void setForceUserActivity(boolean forceUserActivity) {} + + /** Sets the state of whether the user activities are forced or not. */ + default void setLaunchingActivity(boolean launching) {} + + /** Sets the state of whether the scrim is visible or not. */ + default void setScrimsVisibility(int scrimsVisibility) {} + + /** Sets the background blur radius of the notification shade window. */ + default void setBackgroundBlurRadius(int backgroundBlurRadius) {} + + /** Sets the state of whether heads up is showing or not. */ + default void setHeadsUpShowing(boolean showing) {} + + /** Sets whether the wallpaper supports ambient mode or not. */ + default void setWallpaperSupportsAmbientMode(boolean supportsAmbientMode) {} + + /** Gets whether the wallpaper is showing or not. */ + default boolean isShowingWallpaper() { + return false; + } + + /** Sets whether the window was collapsed by force or not. */ + default void setForceWindowCollapsed(boolean force) {} + + /** Sets whether panel is expanded or not. */ + default void setPanelExpanded(boolean isExpanded) {} + + /** Gets whether the panel is expanded or not. */ + default boolean getPanelExpanded() { + return false; + } + + /** Sets the state of whether the remote input is active or not. */ + default void onRemoteInputActive(boolean remoteInputActive) {} + + /** Sets the screen brightness level for when the device is dozing. */ + default void setDozeScreenBrightness(int value) {} + + /** + * Sets whether the screen brightness is forced to the value we use for doze mode by the status + * bar window. No-op if the device does not support dozing. + */ + default void setForceDozeBrightness(boolean forceDozeBrightness) {} + + /** Sets the state of whether sysui is dozing or not. */ + default void setDozing(boolean dozing) {} + + /** Sets the state of whether plugin open is forced or not. */ + default void setForcePluginOpen(boolean forcePluginOpen) {} + + /** Gets whether we are forcing plugin open or not. */ + default boolean getForcePluginOpen() { + return false; + } + + /** Sets the state of whether the notification shade is touchable or not. */ + default void setNotTouchable(boolean notTouchable) {} + + /** Sets a {@link OtherwisedCollapsedListener}. */ + default void setStateListener(OtherwisedCollapsedListener listener) {} + + /** Sets a {@link ForcePluginOpenListener}. */ + default void setForcePluginOpenListener(ForcePluginOpenListener listener) {} + + /** Sets whether the system is in a state where the keyguard is going away. */ + default void setKeyguardGoingAway(boolean goingAway) {} + + /** + * SystemUI may need top-ui to avoid jank when performing animations. After the + * animation is performed, the component should remove itself from the list of features that + * are forcing SystemUI to be top-ui. + */ + default void setRequestTopUi(boolean requestTopUi, String componentTag) {} + + /** + * Custom listener to pipe data back to plugins about whether or not the status bar would be + * collapsed if not for the plugin. + * TODO: Find cleaner way to do this. + */ + interface OtherwisedCollapsedListener { + void setWouldOtherwiseCollapse(boolean otherwiseCollapse); + } + + /** + * Listener to indicate forcePluginOpen has changed + */ + interface ForcePluginOpenListener { + /** + * Called when mState.forcePluginOpen is changed + */ + void onChange(boolean forceOpen); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java index 02a8feec3fa9..1cd1b60ac1ac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java @@ -21,7 +21,6 @@ import android.content.res.Resources; import android.os.Handler; import android.os.Trace; import android.os.UserHandle; -import android.service.notification.NotificationListenerService.Ranking; import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -35,9 +34,9 @@ import com.android.systemui.statusbar.notification.AssistantFeedbackController; import com.android.systemui.statusbar.notification.DynamicChildBindController; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController; import com.android.systemui.statusbar.notification.stack.NotificationListContainer; @@ -491,7 +490,6 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle } } - row.showAppOpsIcons(entry.mActiveAppOps); row.showFeedbackIcon(mAssistantFeedbackController.showFeedbackIndicator(entry)); row.setLastAudiblyAlertedMs(entry.getLastAudiblyAlertedMs()); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java index 0a7ee3b0ebf0..2aba1038a97d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java @@ -28,8 +28,8 @@ import android.widget.TextView; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.settingslib.WirelessUtils; -import com.android.systemui.DemoMode; import com.android.systemui.Dependency; +import com.android.systemui.demomode.DemoModeCommandReceiver; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.statusbar.policy.NetworkController; @@ -40,7 +40,8 @@ import com.android.systemui.tuner.TunerService.Tunable; import java.util.List; -public class OperatorNameView extends TextView implements DemoMode, DarkReceiver, +/** Shows the operator name */ +public class OperatorNameView extends TextView implements DemoModeCommandReceiver, DarkReceiver, SignalCallback, Tunable { private static final String KEY_SHOW_OPERATOR_NAME = "show_operator_name"; @@ -103,14 +104,18 @@ public class OperatorNameView extends TextView implements DemoMode, DarkReceiver @Override public void dispatchDemoCommand(String command, Bundle args) { - if (!mDemoMode && command.equals(COMMAND_ENTER)) { - mDemoMode = true; - } else if (mDemoMode && command.equals(COMMAND_EXIT)) { - mDemoMode = false; - update(); - } else if (mDemoMode && command.equals(COMMAND_OPERATOR)) { - setText(args.getString("name")); - } + setText(args.getString("name")); + } + + @Override + public void onDemoModeStarted() { + mDemoMode = true; + } + + @Override + public void onDemoModeFinished() { + mDemoMode = false; + update(); } private void update() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt index ff13c4e90bba..ba54d1bff6e8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt @@ -30,6 +30,7 @@ import android.view.ViewConfiguration import com.android.systemui.Gefingerpoken import com.android.systemui.Interpolators import com.android.systemui.R +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator @@ -41,13 +42,12 @@ import com.android.systemui.statusbar.phone.HeadsUpManagerPhone import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.phone.ShadeController import javax.inject.Inject -import javax.inject.Singleton import kotlin.math.max /** * A utility class to enable the downward swipe on when pulsing. */ -@Singleton +@SysUISingleton class PulseExpansionHandler @Inject constructor( context: Context, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java index 2bef355d59f3..e9442499a8ce 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java @@ -23,11 +23,14 @@ import android.util.FloatProperty; import android.util.Log; import android.view.animation.Interpolator; +import androidx.annotation.NonNull; + import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.UiEventLogger; import com.android.systemui.DejankUtils; import com.android.systemui.Dumpable; import com.android.systemui.Interpolators; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import com.android.systemui.statusbar.notification.stack.StackStateAnimator; import com.android.systemui.statusbar.policy.CallbackController; @@ -38,12 +41,11 @@ import java.util.ArrayList; import java.util.Comparator; import javax.inject.Inject; -import javax.inject.Singleton; /** * Tracks and reports on {@link StatusBarState}. */ -@Singleton +@SysUISingleton public class StatusBarStateControllerImpl implements SysuiStatusBarStateController, CallbackController<StateListener>, Dumpable { private static final String TAG = "SbStateController"; @@ -101,6 +103,11 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll private boolean mIsDozing; /** + * If the status bar is currently expanded or not. + */ + private boolean mIsExpanded; + + /** * Current {@link #mDozeAmount} animator. */ private ValueAnimator mDarkAnimator; @@ -188,6 +195,26 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll } @Override + public boolean isExpanded() { + return mIsExpanded; + } + + @Override + public boolean setPanelExpanded(boolean expanded) { + if (mIsExpanded == expanded) { + return false; + } + mIsExpanded = expanded; + String tag = getClass().getSimpleName() + "#setIsExpanded"; + DejankUtils.startDetectingBlockingIpcs(tag); + for (RankedListener rl : new ArrayList<>(mListeners)) { + rl.mListener.onExpandedChanged(mIsExpanded); + } + DejankUtils.stopDetectingBlockingIpcs(tag); + return true; + } + + @Override public float getInterpolatedDozeAmount() { return mDozeInterpolator.getInterpolation(mDozeAmount); } @@ -276,7 +303,7 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll } @Override - public void addCallback(StateListener listener) { + public void addCallback(@NonNull StateListener listener) { synchronized (mListeners) { addListenerInternalLocked(listener, Integer.MAX_VALUE); } @@ -316,7 +343,7 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll @Override - public void removeCallback(StateListener listener) { + public void removeCallback(@NonNull StateListener listener) { synchronized (mListeners) { mListeners.removeIf((it) -> it.mListener.equals(listener)); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java index 27e4adee68ba..1ec043cb7670 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java @@ -21,6 +21,7 @@ import android.view.LayoutInflater; import android.view.ViewGroup; import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent; import com.android.systemui.statusbar.phone.LockIcon; import com.android.systemui.statusbar.phone.LockscreenLockIconController; @@ -30,13 +31,12 @@ import com.android.systemui.statusbar.phone.StatusBarWindowView; import com.android.systemui.util.InjectionInflationController; import javax.inject.Inject; -import javax.inject.Singleton; /** * Creates a single instance of super_status_bar and super_notification_shade that can be shared * across various system ui objects. */ -@Singleton +@SysUISingleton public class SuperStatusBarViewFactory { private final Context mContext; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java index 07b35502478f..9f8fe35dfbc9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java @@ -75,6 +75,14 @@ public interface SysuiStatusBarStateController extends StatusBarStateController */ void setDozeAmount(float dozeAmount, boolean animated); + + /** + * Update the expanded state from {@link StatusBar}'s perspective + * @param expanded are we expanded? + * @return {@code true} if the state changed, else {@code false} + */ + boolean setPanelExpanded(boolean expanded); + /** * Sets whether to leave status bar open when hiding keyguard */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java index 442416fd3bea..ea90bdd940a7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java @@ -26,12 +26,13 @@ import android.os.VibrationEffect; import android.os.Vibrator; import android.provider.Settings; +import com.android.systemui.dagger.SysUISingleton; + import javax.inject.Inject; -import javax.inject.Singleton; /** */ -@Singleton +@SysUISingleton public class VibratorHelper { private final Vibrator mVibrator; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java index 992f2da5c3b5..44550b72e521 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java @@ -22,6 +22,7 @@ import android.os.Handler; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.media.MediaDataManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -33,26 +34,24 @@ import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationRemoteInputManager; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationViewHierarchyManager; import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.notification.AssistantFeedbackController; import com.android.systemui.statusbar.notification.DynamicChildBindController; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.NotificationGroupManager; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.RemoteInputUriController; import com.android.systemui.tracing.ProtoTracer; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.concurrency.DelayableExecutor; -import javax.inject.Singleton; - import dagger.Lazy; import dagger.Module; import dagger.Provides; @@ -65,7 +64,7 @@ import dagger.Provides; @Module public interface StatusBarDependenciesModule { /** */ - @Singleton + @SysUISingleton @Provides static NotificationRemoteInputManager provideNotificationRemoteInputManager( Context context, @@ -92,7 +91,7 @@ public interface StatusBarDependenciesModule { } /** */ - @Singleton + @SysUISingleton @Provides static NotificationMediaManager provideNotificationMediaManager( Context context, @@ -117,7 +116,7 @@ public interface StatusBarDependenciesModule { } /** */ - @Singleton + @SysUISingleton @Provides static NotificationListener provideNotificationListener( Context context, @@ -128,7 +127,7 @@ public interface StatusBarDependenciesModule { } /** */ - @Singleton + @SysUISingleton @Provides static SmartReplyController provideSmartReplyController( NotificationEntryManager entryManager, @@ -138,7 +137,7 @@ public interface StatusBarDependenciesModule { } /** */ - @Singleton + @SysUISingleton @Provides static NotificationViewHierarchyManager provideNotificationViewHierarchyManager( Context context, @@ -176,7 +175,7 @@ public interface StatusBarDependenciesModule { * Provides our instance of CommandQueue which is considered optional. */ @Provides - @Singleton + @SysUISingleton static CommandQueue provideCommandQueue(Context context, ProtoTracer protoTracer) { return new CommandQueue(context, protoTracer); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java index b813b6280c12..87a3f0755ec5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java @@ -30,10 +30,10 @@ import android.provider.Settings; import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import javax.inject.Inject; -import javax.inject.Singleton; /** * Determines whether to show any indicators or controls related to notification assistant. @@ -41,7 +41,7 @@ import javax.inject.Singleton; * Flags protect any changes from being shown. Notifications that are adjusted by the assistant * should show an indicator. */ -@Singleton +@SysUISingleton public class AssistantFeedbackController extends ContentObserver { private final Uri FEEDBACK_URI = Settings.Global.getUriFor(Settings.Global.NOTIFICATION_FEEDBACK_ENABLED); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt index 1972b869ba25..c68625c9d9ee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt @@ -24,6 +24,7 @@ import android.service.notification.NotificationListenerService.Ranking import android.service.notification.NotificationListenerService.RankingMap import com.android.internal.statusbar.NotificationVisibility import com.android.internal.widget.ConversationLayout +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow @@ -32,7 +33,6 @@ import com.android.systemui.statusbar.notification.stack.StackStateAnimator import com.android.systemui.statusbar.phone.NotificationGroupManager import java.util.concurrent.ConcurrentHashMap import javax.inject.Inject -import javax.inject.Singleton /** Populates additional information in conversation notifications */ class ConversationNotificationProcessor @Inject constructor( @@ -61,7 +61,7 @@ class ConversationNotificationProcessor @Inject constructor( * Tracks state related to conversation notifications, and updates the UI of existing notifications * when necessary. */ -@Singleton +@SysUISingleton class ConversationNotificationManager @Inject constructor( private val notificationEntryManager: NotificationEntryManager, private val notificationGroupManager: NotificationGroupManager, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java index 2ab329e9574c..9482c17a8769 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java @@ -16,8 +16,10 @@ package com.android.systemui.statusbar.notification; +import android.annotation.Nullable; import android.util.ArraySet; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.StatusBarState; @@ -25,22 +27,21 @@ import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.policy.KeyguardStateController; import javax.inject.Inject; -import javax.inject.Singleton; /** * A controller which dynamically controls the visibility of Notification content */ -@Singleton +@SysUISingleton public class DynamicPrivacyController implements KeyguardStateController.Callback { private final KeyguardStateController mKeyguardStateController; private final NotificationLockscreenUserManager mLockscreenUserManager; private final StatusBarStateController mStateController; - private ArraySet<Listener> mListeners = new ArraySet<>(); + private final ArraySet<Listener> mListeners = new ArraySet<>(); private boolean mLastDynamicUnlocked; private boolean mCacheInvalid; - private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; + @Nullable private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; @Inject DynamicPrivacyController(NotificationLockscreenUserManager notificationLockscreenUserManager, @@ -96,8 +97,7 @@ public class DynamicPrivacyController implements KeyguardStateController.Callbac * contents aren't revealed yet? */ public boolean isInLockedDownShade() { - if (!mStatusBarKeyguardViewManager.isShowing() - || !mKeyguardStateController.isMethodSecure()) { + if (!isStatusBarKeyguardShowing() || !mKeyguardStateController.isMethodSecure()) { return false; } int state = mStateController.getState(); @@ -110,6 +110,10 @@ public class DynamicPrivacyController implements KeyguardStateController.Callbac return true; } + private boolean isStatusBarKeyguardShowing() { + return mStatusBarKeyguardViewManager != null && mStatusBarKeyguardViewManager.isShowing(); + } + public void setStatusBarKeyguardViewManager( StatusBarKeyguardViewManager statusBarKeyguardViewManager) { mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ForegroundServiceDismissalFeatureController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ForegroundServiceDismissalFeatureController.kt index dfc2fc1c4584..314051c8ce6c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ForegroundServiceDismissalFeatureController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ForegroundServiceDismissalFeatureController.kt @@ -19,9 +19,9 @@ package com.android.systemui.statusbar.notification import android.content.Context import android.provider.DeviceConfig import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NOTIFICATIONS_ALLOW_FGS_DISMISSAL +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.util.DeviceConfigProxy import javax.inject.Inject -import javax.inject.Singleton private var sIsEnabled: Boolean? = null @@ -29,7 +29,7 @@ private var sIsEnabled: Boolean? = null * Feature controller for NOTIFICATIONS_ALLOW_FGS_DISMISSAL config. */ // TODO: this is really boilerplatey, make a base class that just wraps the device config -@Singleton +@SysUISingleton class ForegroundServiceDismissalFeatureController @Inject constructor( val proxy: DeviceConfigProxy, val context: Context diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java index 312b2c52b42e..ea614fb210b3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java @@ -53,6 +53,7 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SystemUI; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.stackdivider.Divider; import com.android.systemui.statusbar.CommandQueue; @@ -63,12 +64,11 @@ import java.util.List; import java.util.concurrent.Executor; import javax.inject.Inject; -import javax.inject.Singleton; /** The class to show notification(s) of instant apps. This may show multiple notifications on * splitted screen. */ -@Singleton +@SysUISingleton public class InstantAppNotifier extends SystemUI implements CommandQueue.Callbacks, KeyguardStateController.Callback { private static final String TAG = "InstantAppNotifier"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index e1ff872456eb..b5f1c7ff9b62 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -48,6 +48,7 @@ import com.android.systemui.statusbar.NotificationUiAdjustment; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationRankingManager; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java index 6335a09cde2b..590ccf830a78 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java @@ -29,6 +29,7 @@ import android.service.notification.StatusBarNotification; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Dependency; import com.android.systemui.ForegroundServiceController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.media.MediaFeatureFlag; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationLockscreenUserManager; @@ -37,13 +38,12 @@ import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.ShadeController; import javax.inject.Inject; -import javax.inject.Singleton; /** Component which manages the various reasons a notification might be filtered out.*/ // TODO: delete NotificationFilter.java after migrating to new NotifPipeline b/145659174. // Notification filtering is taken care of across the different Coordinators (mostly // KeyguardCoordinator.java) -@Singleton +@SysUISingleton public class NotificationFilter { private final NotificationGroupManager mGroupManager = Dependency.get( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt index 0469176255c2..1326d920fe42 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification import android.animation.ObjectAnimator import android.util.FloatProperty import com.android.systemui.Interpolators +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.notification.collection.NotificationEntry @@ -26,16 +27,13 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll import com.android.systemui.statusbar.notification.stack.StackStateAnimator import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.phone.KeyguardBypassController -import com.android.systemui.statusbar.phone.NotificationIconAreaController import com.android.systemui.statusbar.phone.PanelExpansionListener import com.android.systemui.statusbar.policy.HeadsUpManager import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener - import javax.inject.Inject -import javax.inject.Singleton import kotlin.math.min -@Singleton +@SysUISingleton class NotificationWakeUpCoordinator @Inject constructor( private val mHeadsUpManager: HeadsUpManager, private val statusBarStateController: StatusBarStateController, @@ -99,7 +97,6 @@ class NotificationWakeUpCoordinator @Inject constructor( } private var collapsedEnoughToHide: Boolean = false - lateinit var iconAreaController: NotificationIconAreaController var pulsing: Boolean = false set(value) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt index 57f8a6a3abef..17e62890aadd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt @@ -46,7 +46,14 @@ data class ListAttachState private constructor( /** * The [NotifPromoter] promoting this entry to top-level, if any. Always null for [GroupEntry]s. */ - var promoter: NotifPromoter? + var promoter: NotifPromoter?, + + /** + * If the [VisualStabilityManager] is suppressing group or section changes for this entry, + * suppressedChanges will contain the new parent or section that we would have assigned to + * the entry had it not been suppressed by the VisualStabilityManager. + */ + var suppressedChanges: SuppressedAttachState ) { /** Copies the state of another instance. */ @@ -56,6 +63,7 @@ data class ListAttachState private constructor( sectionIndex = other.sectionIndex excludingFilter = other.excludingFilter promoter = other.promoter + suppressedChanges.clone(other.suppressedChanges) } /** Resets back to a "clean" state (the same as created by the factory method) */ @@ -65,6 +73,7 @@ data class ListAttachState private constructor( sectionIndex = -1 excludingFilter = null promoter = null + suppressedChanges.reset() } companion object { @@ -75,7 +84,8 @@ data class ListAttachState private constructor( null, -1, null, - null) + null, + SuppressedAttachState.create()) } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java index 3a0520115d67..786c97d03712 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java @@ -167,6 +167,23 @@ public class ListDumper { .append(" "); } + if (notifEntry.getAttachState().getSuppressedChanges().getParent() != null) { + rksb.append("suppressedParent=") + .append(notifEntry.getAttachState().getSuppressedChanges() + .getParent().getKey()) + .append(" "); + } + + if (notifEntry.getAttachState().getSuppressedChanges().getSection() != null) { + rksb.append("suppressedSectionIndex=") + .append(notifEntry.getAttachState().getSuppressedChanges() + .getSectionIndex()) + .append(" sectionName=") + .append(notifEntry.getAttachState().getSuppressedChanges() + .getSection().getName()) + .append(" "); + } + if (hasBeenInteractedWith) { rksb.append("interacted=yes "); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java index 285cf7abce20..90492b5d606d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java @@ -59,6 +59,7 @@ import androidx.annotation.NonNull; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; import com.android.systemui.dump.LogBufferEulogizer; import com.android.systemui.statusbar.FeatureFlags; @@ -98,7 +99,6 @@ import java.util.Queue; import java.util.concurrent.TimeUnit; import javax.inject.Inject; -import javax.inject.Singleton; /** * Keeps a record of all of the "active" notifications, i.e. the notifications that are currently @@ -123,7 +123,7 @@ import javax.inject.Singleton; * events occur. */ @MainThread -@Singleton +@SysUISingleton public class NotifCollection implements Dumpable { private final IStatusBarService mStatusBarService; private final SystemClock mClock; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java index aaf5c4d6594b..8562a2e55a4f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.collection; import com.android.internal.statusbar.IStatusBarService; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.InflationException; import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl; @@ -24,14 +25,13 @@ import com.android.systemui.statusbar.notification.row.NotifInflationErrorManage import com.android.systemui.statusbar.notification.row.NotificationContentInflater; import javax.inject.Inject; -import javax.inject.Singleton; /** * Handles notification inflating, rebinding, and inflation aborting. * * Currently a wrapper for NotificationRowBinderImpl. */ -@Singleton +@SysUISingleton public class NotifInflaterImpl implements NotifInflater { private final IStatusBarService mStatusBarService; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java index 17899e99275b..05dd4df1f2ce 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.collection; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener; @@ -24,6 +25,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection; +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor; @@ -33,7 +35,6 @@ import java.util.Collection; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * The system that constructs the "shade list", the filtered, grouped, and sorted list of @@ -68,7 +69,7 @@ import javax.inject.Singleton; * 9. OnBeforeRenderListListeners are fired ({@link #addOnBeforeRenderListListener}) * 9. The list is handed off to the view layer to be rendered */ -@Singleton +@SysUISingleton public class NotifPipeline implements CommonNotifCollection { private final NotifCollection mNotifCollection; private final ShadeListBuilder mShadeListBuilder; @@ -161,6 +162,14 @@ public class NotifPipeline implements CommonNotifCollection { } /** + * StabilityManager that is used to determine whether to suppress group and section changes. + * This should only be set once. + */ + public void setVisualStabilityManager(NotifStabilityManager notifStabilityManager) { + mShadeListBuilder.setNotifStabilityManager(notifStabilityManager); + } + + /** * Comparators that are used to sort top-level entries that share the same section. The * comparators are executed in order until one of them returns a non-zero result. If all return * zero, the pipeline falls back to sorting by rank (and, failing that, Notification.when). diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java index d45f89cb6fe5..6cbebf803511 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java @@ -21,6 +21,7 @@ import static com.android.systemui.statusbar.notification.collection.listbuilder import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_FINALIZE_FILTERING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_FINALIZING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_GROUPING; +import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_GROUP_STABILIZING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_IDLE; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_PRE_GROUP_FILTERING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_RESETTING; @@ -35,6 +36,7 @@ import android.util.Pair; import androidx.annotation.NonNull; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.NotificationInteractionTracker; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener; @@ -47,6 +49,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection; +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable; import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener; import com.android.systemui.util.Assert; @@ -63,7 +66,6 @@ import java.util.Map; import java.util.Objects; import javax.inject.Inject; -import javax.inject.Singleton; /** * The second half of {@link NotifPipeline}. Sits downstream of the NotifCollection and transforms @@ -71,7 +73,7 @@ import javax.inject.Singleton; * notifications that are currently present in the notification shade. */ @MainThread -@Singleton +@SysUISingleton public class ShadeListBuilder implements Dumpable { private final SystemClock mSystemClock; private final ShadeListBuilderLogger mLogger; @@ -90,6 +92,7 @@ public class ShadeListBuilder implements Dumpable { private final List<NotifFilter> mNotifFinalizeFilters = new ArrayList<>(); private final List<NotifComparator> mNotifComparators = new ArrayList<>(); private final List<NotifSection> mNotifSections = new ArrayList<>(); + @Nullable private NotifStabilityManager mNotifStabilityManager; private final List<OnBeforeTransformGroupsListener> mOnBeforeTransformGroupsListeners = new ArrayList<>(); @@ -109,7 +112,8 @@ public class ShadeListBuilder implements Dumpable { SystemClock systemClock, ShadeListBuilderLogger logger, DumpManager dumpManager, - NotificationInteractionTracker interactionTracker) { + NotificationInteractionTracker interactionTracker + ) { Assert.isMainThread(); mSystemClock = systemClock; mLogger = logger; @@ -200,6 +204,22 @@ public class ShadeListBuilder implements Dumpable { } } + void setNotifStabilityManager(NotifStabilityManager notifStabilityManager) { + Assert.isMainThread(); + mPipelineState.requireState(STATE_IDLE); + + if (mNotifStabilityManager != null) { + throw new IllegalStateException( + "Attempting to set the NotifStabilityManager more than once. There should " + + "only be one visual stability manager. Manager is being set by " + + mNotifStabilityManager.getName() + " and " + + notifStabilityManager.getName()); + } + + mNotifStabilityManager = notifStabilityManager; + mNotifStabilityManager.setInvalidationListener(this::onReorderingAllowedInvalidated); + } + void setComparators(List<NotifComparator> comparators) { Assert.isMainThread(); mPipelineState.requireState(STATE_IDLE); @@ -237,6 +257,16 @@ public class ShadeListBuilder implements Dumpable { rebuildListIfBefore(STATE_PRE_GROUP_FILTERING); } + private void onReorderingAllowedInvalidated(NotifStabilityManager stabilityManager) { + Assert.isMainThread(); + + mLogger.logReorderingAllowedInvalidated( + stabilityManager.getName(), + mPipelineState.getState()); + + rebuildListIfBefore(STATE_GROUPING); + } + private void onPromoterInvalidated(NotifPromoter promoter) { Assert.isMainThread(); @@ -285,6 +315,7 @@ public class ShadeListBuilder implements Dumpable { // Step 1: Reset notification states mPipelineState.incrementTo(STATE_RESETTING); resetNotifs(); + onBeginRun(); // Step 2: Filter out any notifications that shouldn't be shown right now mPipelineState.incrementTo(STATE_PRE_GROUP_FILTERING); @@ -303,6 +334,10 @@ public class ShadeListBuilder implements Dumpable { promoteNotifs(mNotifList); pruneIncompleteGroups(mNotifList); + // Step 4.5: Reassign/revert any groups to maintain visual stability + mPipelineState.incrementTo(STATE_GROUP_STABILIZING); + stabilizeGroupingNotifs(mNotifList); + // Step 5: Sort // Assign each top-level entry a section, then sort the list by section and then within // section by our list of custom comparators @@ -472,6 +507,28 @@ public class ShadeListBuilder implements Dumpable { } } + private void stabilizeGroupingNotifs(List<ListEntry> list) { + if (mNotifStabilityManager == null) { + return; + } + + for (int i = 0; i < list.size(); i++) { + final ListEntry tle = list.get(i); + if (tle.getPreviousAttachState().getParent() == null) { + continue; // new entries are allowed + } + + final GroupEntry prevParent = tle.getPreviousAttachState().getParent(); + final GroupEntry assignedParent = tle.getParent(); + if (prevParent != assignedParent) { + if (!mNotifStabilityManager.isGroupChangeAllowed(tle.getRepresentativeEntry())) { + tle.getAttachState().getSuppressedChanges().setParent(assignedParent); + tle.setParent(prevParent); + } + } + } + } + private void promoteNotifs(List<ListEntry> list) { for (int i = 0; i < list.size(); i++) { final ListEntry tle = list.get(i); @@ -650,9 +707,18 @@ public class ShadeListBuilder implements Dumpable { mLogger.logParentChanged(mIterationCount, prev.getParent(), curr.getParent()); } + if (curr.getSuppressedChanges().getParent() != null) { + mLogger.logParentChangeSuppressed( + mIterationCount, + curr.getSuppressedChanges().getParent(), + curr.getParent()); + } + if (curr.getExcludingFilter() != prev.getExcludingFilter()) { mLogger.logFilterChanged( - mIterationCount, prev.getExcludingFilter(), curr.getExcludingFilter()); + mIterationCount, + prev.getExcludingFilter(), + curr.getExcludingFilter()); } // When something gets detached, its promoter and section are always set to null, so @@ -661,7 +727,9 @@ public class ShadeListBuilder implements Dumpable { if (!wasDetached && curr.getPromoter() != prev.getPromoter()) { mLogger.logPromoterChanged( - mIterationCount, prev.getPromoter(), curr.getPromoter()); + mIterationCount, + prev.getPromoter(), + curr.getPromoter()); } if (!wasDetached && curr.getSection() != prev.getSection()) { @@ -672,6 +740,20 @@ public class ShadeListBuilder implements Dumpable { curr.getSection(), curr.getSectionIndex()); } + + if (curr.getSuppressedChanges().getSection() != null) { + mLogger.logSectionChangeSuppressed( + mIterationCount, + curr.getSuppressedChanges().getSection(), + curr.getSuppressedChanges().getSectionIndex(), + curr.getSection()); + } + } + } + + private void onBeginRun() { + if (mNotifStabilityManager != null) { + mNotifStabilityManager.onBeginRun(); } } @@ -681,6 +763,10 @@ public class ShadeListBuilder implements Dumpable { callOnCleanup(mNotifFinalizeFilters); callOnCleanup(mNotifComparators); callOnCleanup(mNotifSections); + + if (mNotifStabilityManager != null) { + callOnCleanup(List.of(mNotifStabilityManager)); + } } private void callOnCleanup(List<? extends Pluggable<?>> pluggables) { @@ -770,12 +856,32 @@ public class ShadeListBuilder implements Dumpable { } private Pair<NotifSection, Integer> applySections(ListEntry entry) { - final Pair<NotifSection, Integer> sectionWithIndex = findSection(entry); - final NotifSection section = sectionWithIndex.first; - final Integer sectionIndex = sectionWithIndex.second; + Pair<NotifSection, Integer> sectionWithIndex = findSection(entry); + final ListAttachState prevAttachState = entry.getPreviousAttachState(); + + // are we changing sections of this entry? + if (mNotifStabilityManager != null + && prevAttachState.getParent() != null + && (sectionWithIndex.first != prevAttachState.getSection() + || sectionWithIndex.second != prevAttachState.getSectionIndex())) { + + // are section changes allowed? + if (!mNotifStabilityManager.isSectionChangeAllowed( + entry.getRepresentativeEntry())) { + entry.getAttachState().getSuppressedChanges().setSection( + sectionWithIndex.first); + entry.getAttachState().getSuppressedChanges().setSectionIndex( + sectionWithIndex.second); + + // keep the previous section + sectionWithIndex = new Pair( + prevAttachState.getSection(), + prevAttachState.getSectionIndex()); + } + } - entry.getAttachState().setSection(section); - entry.getAttachState().setSectionIndex(sectionIndex); + entry.getAttachState().setSection(sectionWithIndex.first); + entry.getAttachState().setSectionIndex(sectionWithIndex.second); return sectionWithIndex; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt new file mode 100644 index 000000000000..52612365712e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt @@ -0,0 +1,63 @@ +/* + * 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.collection + +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection + +/** + * Stores the suppressed state that [ShadeListBuilder] assigned to this [ListEntry] before the + * VisualStabilityManager suppressed group and section changes. + */ +data class SuppressedAttachState private constructor( + /** + * Null if not attached to the current shade list. If top-level, then the shade list root. If + * part of a group, then that group's GroupEntry. + */ + var parent: GroupEntry?, + + /** + * The assigned section for this ListEntry. If the child of the group, this will be the + * parent's section. Null if not attached to the list. + */ + var section: NotifSection?, + var sectionIndex: Int +) { + + /** Copies the state of another instance. */ + fun clone(other: SuppressedAttachState) { + parent = other.parent + section = other.section + sectionIndex = other.sectionIndex + } + + /** Resets back to a "clean" state (the same as created by the factory method) */ + fun reset() { + parent = null + section = null + sectionIndex = -1 + } + + companion object { + @JvmStatic + fun create(): SuppressedAttachState { + return SuppressedAttachState( + null, + null, + -1) + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt index a0f9dc91ce68..5dc0dcc4d717 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt @@ -20,13 +20,13 @@ import android.content.Context import android.content.pm.PackageManager import android.service.notification.StatusBarNotification import android.util.Log +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener import com.android.systemui.statusbar.phone.StatusBar import javax.inject.Inject -import javax.inject.Singleton -@Singleton +@SysUISingleton class TargetSdkResolver @Inject constructor( private val context: Context ) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java index 68ec6b620a53..0b9bded5ef58 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java @@ -19,28 +19,24 @@ package com.android.systemui.statusbar.notification.collection.coordinator; import static android.app.NotificationManager.IMPORTANCE_MIN; import android.app.Notification; -import android.os.UserHandle; import android.service.notification.StatusBarNotification; -import android.util.ArraySet; import com.android.systemui.ForegroundServiceController; import com.android.systemui.appops.AppOpsController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection; -import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender; -import com.android.systemui.util.Assert; import com.android.systemui.util.concurrency.DelayableExecutor; import java.util.HashMap; import java.util.Map; import javax.inject.Inject; -import javax.inject.Singleton; /** * Handles ForegroundService and AppOp interactions with notifications. @@ -55,7 +51,7 @@ import javax.inject.Singleton; * frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener * frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender */ -@Singleton +@SysUISingleton public class AppOpsCoordinator implements Coordinator { private static final String TAG = "AppOpsCoordinator"; @@ -82,14 +78,9 @@ public class AppOpsCoordinator implements Coordinator { // extend the lifetime of foreground notification services to show for at least 5 seconds mNotifPipeline.addNotificationLifetimeExtender(mForegroundLifetimeExtender); - // listen for new notifications to add appOps - mNotifPipeline.addCollectionListener(mNotifCollectionListener); - // filter out foreground service notifications that aren't necessary anymore mNotifPipeline.addPreGroupFilter(mNotifFilter); - // when appOps change, update any relevant notifications to update appOps for - mAppOpsController.addCallback(ForegroundServiceController.APP_OPS, this::onAppOpsChanged); } public NotifSection getSection() { @@ -186,35 +177,6 @@ public class AppOpsCoordinator implements Coordinator { }; /** - * Adds appOps to incoming and updating notifications - */ - private NotifCollectionListener mNotifCollectionListener = new NotifCollectionListener() { - @Override - public void onEntryAdded(NotificationEntry entry) { - tagAppOps(entry); - } - - @Override - public void onEntryUpdated(NotificationEntry entry) { - tagAppOps(entry); - } - - private void tagAppOps(NotificationEntry entry) { - final StatusBarNotification sbn = entry.getSbn(); - // note: requires that the ForegroundServiceController is updating their appOps first - ArraySet<Integer> activeOps = - mForegroundServiceController.getAppOps( - sbn.getUser().getIdentifier(), - sbn.getPackageName()); - - entry.mActiveAppOps.clear(); - if (activeOps != null) { - entry.mActiveAppOps.addAll(activeOps); - } - } - }; - - /** * Puts foreground service notifications into its own section. */ private final NotifSection mNotifSection = new NotifSection("ForegroundService") { @@ -230,53 +192,4 @@ public class AppOpsCoordinator implements Coordinator { return false; } }; - - private void onAppOpsChanged(int code, int uid, String packageName, boolean active) { - mMainExecutor.execute(() -> handleAppOpsChanged(code, uid, packageName, active)); - } - - /** - * Update the appOp for the posted notification associated with the current foreground service - * - * @param code code for appOp to add/remove - * @param uid of user the notification is sent to - * @param packageName package that created the notification - * @param active whether the appOpCode is active or not - */ - private void handleAppOpsChanged(int code, int uid, String packageName, boolean active) { - Assert.isMainThread(); - - int userId = UserHandle.getUserId(uid); - - // Update appOps of the app's posted notifications with standard layouts - final ArraySet<String> notifKeys = - mForegroundServiceController.getStandardLayoutKeys(userId, packageName); - if (notifKeys != null) { - boolean changed = false; - for (int i = 0; i < notifKeys.size(); i++) { - final NotificationEntry entry = findNotificationEntryWithKey(notifKeys.valueAt(i)); - if (entry != null - && uid == entry.getSbn().getUid() - && packageName.equals(entry.getSbn().getPackageName())) { - if (active) { - changed |= entry.mActiveAppOps.add(code); - } else { - changed |= entry.mActiveAppOps.remove(code); - } - } - } - if (changed) { - mNotifFilter.invalidateList(); - } - } - } - - private NotificationEntry findNotificationEntryWithKey(String key) { - for (NotificationEntry entry : mNotifPipeline.getAllNotifs()) { - if (entry.getKey().equals(key)) { - return entry; - } - } - return null; - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java index 08462c183bd9..4ddc1dc8498d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator; import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.collection.NotifCollection; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -28,7 +29,6 @@ import java.util.HashSet; import java.util.Set; import javax.inject.Inject; -import javax.inject.Singleton; /** * Coordinates hiding, intercepting (the dismissal), and deletion of bubbled notifications. @@ -50,7 +50,7 @@ import javax.inject.Singleton; * respond to app-cancellations (ie: remove the bubble if the app cancels the notification). * */ -@Singleton +@SysUISingleton public class BubbleCoordinator implements Coordinator { private static final String TAG = "BubbleCoordinator"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt index 1a9de8829faf..c8e859f27a5c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry @@ -24,14 +25,13 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON import javax.inject.Inject -import javax.inject.Singleton /** * A Conversation/People Coordinator that: * - Elevates important conversation notifications * - Puts conversations into its own people section. @see [NotifCoordinators] for section ordering. */ -@Singleton +@SysUISingleton class ConversationCoordinator @Inject constructor( private val peopleNotificationIdentifier: PeopleNotificationIdentifier ) : Coordinator { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java index 625d1b9686e9..47928b42ed5e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java @@ -23,20 +23,20 @@ import android.content.pm.PackageManager; import android.os.RemoteException; import android.service.notification.StatusBarNotification; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import javax.inject.Inject; -import javax.inject.Singleton; /** * Filters out most notifications when the device is unprovisioned. * Special notifications with extra permissions and tags won't be filtered out even when the * device is unprovisioned. */ -@Singleton +@SysUISingleton public class DeviceProvisionedCoordinator implements Coordinator { private static final String TAG = "DeviceProvisionedCoordinator"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java index 72597afc3b90..6e6cecaf62fa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java @@ -21,6 +21,7 @@ import static com.android.systemui.statusbar.notification.interruption.HeadsUpCo import android.annotation.Nullable; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; @@ -37,7 +38,6 @@ import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import java.util.Objects; import javax.inject.Inject; -import javax.inject.Singleton; /** * Coordinates heads up notification (HUN) interactions with the notification pipeline based on @@ -53,7 +53,7 @@ import javax.inject.Singleton; * * Note: The inflation callback in {@link PreparationCoordinator} handles showing HUNs. */ -@Singleton +@SysUISingleton public class HeadsUpCoordinator implements Coordinator { private static final String TAG = "HeadsUpCoordinator"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java index 95ba759df547..318cdb171fa5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java @@ -34,6 +34,7 @@ import androidx.annotation.MainThread; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.notification.NotificationUtils; @@ -46,12 +47,11 @@ import com.android.systemui.statusbar.notification.collection.provider.HighPrior import com.android.systemui.statusbar.policy.KeyguardStateController; import javax.inject.Inject; -import javax.inject.Singleton; /** * Filters low priority and privacy-sensitive notifications from the lockscreen. */ -@Singleton +@SysUISingleton public class KeyguardCoordinator implements Coordinator { private static final String TAG = "KeyguardCoordinator"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java index a09c6509e65e..87ca717982f5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.notification.collection.NotifPipeline; @@ -31,17 +32,17 @@ import java.util.ArrayList; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * Handles the attachment of {@link Coordinator}s to the {@link NotifPipeline} so that the * Coordinators can register their respective callbacks. */ -@Singleton +@SysUISingleton public class NotifCoordinators implements Dumpable { private static final String TAG = "NotifCoordinators"; private final List<Coordinator> mCoordinators = new ArrayList<>(); private final List<NotifSection> mOrderedSections = new ArrayList<>(); + /** * Creates all the coordinators. */ @@ -58,7 +59,8 @@ public class NotifCoordinators implements Dumpable { HeadsUpCoordinator headsUpCoordinator, ConversationCoordinator conversationCoordinator, PreparationCoordinator preparationCoordinator, - MediaCoordinator mediaCoordinator) { + MediaCoordinator mediaCoordinator, + VisualStabilityCoordinator visualStabilityCoordinator) { dumpManager.registerDumpable(TAG, this); mCoordinators.add(new HideLocallyDismissedNotifsCoordinator()); @@ -70,6 +72,7 @@ public class NotifCoordinators implements Dumpable { mCoordinators.add(bubbleCoordinator); mCoordinators.add(mediaCoordinator); mCoordinators.add(conversationCoordinator); + mCoordinators.add(visualStabilityCoordinator); if (featureFlags.isNewNotifPipelineRenderingEnabled()) { mCoordinators.add(headsUpCoordinator); mCoordinators.add(preparationCoordinator); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java index 3e110671d174..31826c7219de 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java @@ -28,6 +28,7 @@ import android.util.ArraySet; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.collection.GroupEntry; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; @@ -48,7 +49,6 @@ import java.util.Map; import java.util.Set; import javax.inject.Inject; -import javax.inject.Singleton; /** * Kicks off core notification inflation and view rebinding when a notification is added or updated. @@ -57,7 +57,7 @@ import javax.inject.Singleton; * If a notification was uninflated, this coordinator will filter the notification out from the * {@link ShadeListBuilder} until it is inflated. */ -@Singleton +@SysUISingleton public class PreparationCoordinator implements Coordinator { private static final String TAG = "PreparationCoordinator"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java index 0d2f9da77db7..a32b1636057b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; @@ -25,7 +26,6 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; import javax.inject.Inject; -import javax.inject.Singleton; /** * Filters out NotificationEntries based on its Ranking and dozing state. @@ -34,7 +34,7 @@ import javax.inject.Singleton; * - whether the notification's app is suspended or hiding its notifications * - whether DND settings are hiding notifications from ambient display or the notification list */ -@Singleton +@SysUISingleton public class RankingCoordinator implements Coordinator { private static final String TAG = "RankingNotificationCoordinator"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java new file mode 100644 index 000000000000..08030f8201a2 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java @@ -0,0 +1,205 @@ +/* + * 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.collection.coordinator; + +import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; +import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING; + +import android.annotation.NonNull; + +import androidx.annotation.VisibleForTesting; + +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.NotificationViewHierarchyManager; +import com.android.systemui.statusbar.notification.collection.NotifPipeline; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager; +import com.android.systemui.statusbar.policy.HeadsUpManager; +import com.android.systemui.util.concurrency.DelayableExecutor; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; + +/** + * Ensures that notifications are visually stable if the user is looking at the notifications. + * Group and section changes are re-allowed when the notification entries are no longer being + * viewed. + * + * Previously this was implemented in the view-layer {@link NotificationViewHierarchyManager} by + * {@link com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager}. + * This is now integrated in the data-layer via + * {@link com.android.systemui.statusbar.notification.collection.ShadeListBuilder}. + */ +@SysUISingleton +public class VisualStabilityCoordinator implements Coordinator { + private final DelayableExecutor mDelayableExecutor; + private final WakefulnessLifecycle mWakefulnessLifecycle; + private final StatusBarStateController mStatusBarStateController; + private final HeadsUpManager mHeadsUpManager; + + private boolean mScreenOn; + private boolean mPanelExpanded; + private boolean mPulsing; + + private boolean mReorderingAllowed; + private boolean mIsSuppressingGroupChange = false; + private final Set<String> mEntriesWithSuppressedSectionChange = new HashSet<>(); + + // key: notification key that can temporarily change its section + // value: runnable that when run removes its associated RemoveOverrideSuppressionRunnable + // from the DelayableExecutor's queue + private Map<String, Runnable> mEntriesThatCanChangeSection = new HashMap<>(); + + @VisibleForTesting + protected static final long ALLOW_SECTION_CHANGE_TIMEOUT = 500; + + @Inject + public VisualStabilityCoordinator( + HeadsUpManager headsUpManager, + WakefulnessLifecycle wakefulnessLifecycle, + StatusBarStateController statusBarStateController, + DelayableExecutor delayableExecutor + ) { + mHeadsUpManager = headsUpManager; + mWakefulnessLifecycle = wakefulnessLifecycle; + mStatusBarStateController = statusBarStateController; + mDelayableExecutor = delayableExecutor; + } + + @Override + public void attach(NotifPipeline pipeline) { + mWakefulnessLifecycle.addObserver(mWakefulnessObserver); + mScreenOn = mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE + || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING; + + mStatusBarStateController.addCallback(mStatusBarStateControllerListener); + mPulsing = mStatusBarStateController.isPulsing(); + + pipeline.setVisualStabilityManager(mNotifStabilityManager); + } + + private final NotifStabilityManager mNotifStabilityManager = + new NotifStabilityManager("VisualStabilityCoordinator") { + @Override + public void onBeginRun() { + mIsSuppressingGroupChange = false; + mEntriesWithSuppressedSectionChange.clear(); + } + + @Override + public boolean isGroupChangeAllowed(NotificationEntry entry) { + final boolean isGroupChangeAllowedForEntry = + mReorderingAllowed || mHeadsUpManager.isAlerting(entry.getKey()); + mIsSuppressingGroupChange |= isGroupChangeAllowedForEntry; + return isGroupChangeAllowedForEntry; + } + + @Override + public boolean isSectionChangeAllowed(NotificationEntry entry) { + final boolean isSectionChangeAllowedForEntry = + mReorderingAllowed + || mHeadsUpManager.isAlerting(entry.getKey()) + || mEntriesThatCanChangeSection.containsKey(entry.getKey()); + if (isSectionChangeAllowedForEntry) { + mEntriesWithSuppressedSectionChange.add(entry.getKey()); + } + return isSectionChangeAllowedForEntry; + } + }; + + private void updateAllowedStates() { + mReorderingAllowed = isReorderingAllowed(); + if (mReorderingAllowed && (mIsSuppressingGroupChange || isSuppressingSectionChange())) { + mNotifStabilityManager.invalidateList(); + } + } + + private boolean isSuppressingSectionChange() { + return !mEntriesWithSuppressedSectionChange.isEmpty(); + } + + private boolean isReorderingAllowed() { + return (!mScreenOn || !mPanelExpanded) && !mPulsing; + } + + /** + * Allows this notification entry to be re-ordered in the notification list temporarily until + * the timeout has passed. + * + * Typically this is allowed because the user has directly changed something about the + * notification and we are reordering based on the user's change. + * + * @param entry notification entry that can change sections even if isReorderingAllowed is false + * @param now current time SystemClock.uptimeMillis + */ + public void temporarilyAllowSectionChanges(@NonNull NotificationEntry entry, long now) { + final String entryKey = entry.getKey(); + final boolean wasSectionChangeAllowed = + mNotifStabilityManager.isSectionChangeAllowed(entry); + + // If it exists, cancel previous timeout + if (mEntriesThatCanChangeSection.containsKey(entryKey)) { + mEntriesThatCanChangeSection.get(entryKey).run(); + } + + // Schedule & store new timeout cancellable + mEntriesThatCanChangeSection.put( + entryKey, + mDelayableExecutor.executeAtTime( + () -> mEntriesThatCanChangeSection.remove(entryKey), + now + ALLOW_SECTION_CHANGE_TIMEOUT)); + + if (!wasSectionChangeAllowed) { + mNotifStabilityManager.invalidateList(); + } + } + + final StatusBarStateController.StateListener mStatusBarStateControllerListener = + new StatusBarStateController.StateListener() { + @Override + public void onPulsingChanged(boolean pulsing) { + mPulsing = pulsing; + updateAllowedStates(); + } + + @Override + public void onExpandedChanged(boolean expanded) { + mPanelExpanded = expanded; + updateAllowedStates(); + } + }; + + final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() { + @Override + public void onFinishedGoingToSleep() { + mScreenOn = false; + updateAllowedStates(); + } + + @Override + public void onStartedWakingUp() { + mScreenOn = true; + updateAllowedStates(); + } + }; +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java index 73c0fdc56b8d..6089aa26fe71 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.collection.inflation; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.notification.collection.GroupEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -25,13 +26,12 @@ import com.android.systemui.statusbar.notification.row.RowContentBindStage; import com.android.systemui.statusbar.phone.NotificationGroupManager; import javax.inject.Inject; -import javax.inject.Singleton; /** * Helper class that provide methods to help check when we need to inflate a low priority version * ot notification content. */ -@Singleton +@SysUISingleton public class LowPriorityInflationHelper { private final FeatureFlags mFeatureFlags; private final NotificationGroupManager mGroupManager; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java index f90ec0b4f42a..7c061aad7b4a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java @@ -24,6 +24,7 @@ import android.os.Build; import android.view.ViewGroup; import com.android.internal.util.NotificationMessagingUtil; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; @@ -44,10 +45,9 @@ import com.android.systemui.statusbar.notification.stack.NotificationListContain import javax.inject.Inject; import javax.inject.Provider; -import javax.inject.Singleton; /** Handles inflating and updating views for notifications. */ -@Singleton +@SysUISingleton public class NotificationRowBinderImpl implements NotificationRowBinder { private static final String TAG = "NotificationViewManager"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnDismissCallbackImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnUserInteractionCallbackImpl.java index 36adf9b87674..19a356b89f18 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnDismissCallbackImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnUserInteractionCallbackImpl.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.collection.inflation; import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL; +import android.os.SystemClock; import android.service.notification.NotificationListenerService; import android.service.notification.NotificationStats; @@ -26,35 +27,43 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.notification.collection.NotifCollection; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.coordinator.VisualStabilityCoordinator; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.logging.NotificationLogger; -import com.android.systemui.statusbar.notification.row.OnDismissCallback; +import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback; import com.android.systemui.statusbar.policy.HeadsUpManager; /** - * Callback used when a user: - * 1. Manually dismisses a notification {@see ExpandableNotificationRow}. - * 2. Clicks on a notification with flag {@link android.app.Notification#FLAG_AUTO_CANCEL}. - * {@see StatusBarNotificationActivityStarter} + * Callback for when a user interacts with a {@see ExpandableNotificationRow}. Sends relevant + * information about the interaction to the notification pipeline. */ -public class OnDismissCallbackImpl implements OnDismissCallback { +public class OnUserInteractionCallbackImpl implements OnUserInteractionCallback { private final NotifPipeline mNotifPipeline; private final NotifCollection mNotifCollection; private final HeadsUpManager mHeadsUpManager; private final StatusBarStateController mStatusBarStateController; + private final VisualStabilityCoordinator mVisualStabilityCoordinator; - public OnDismissCallbackImpl( + public OnUserInteractionCallbackImpl( NotifPipeline notifPipeline, NotifCollection notifCollection, HeadsUpManager headsUpManager, - StatusBarStateController statusBarStateController + StatusBarStateController statusBarStateController, + VisualStabilityCoordinator visualStabilityCoordinator ) { mNotifPipeline = notifPipeline; mNotifCollection = notifCollection; mHeadsUpManager = headsUpManager; mStatusBarStateController = statusBarStateController; + mVisualStabilityCoordinator = visualStabilityCoordinator; } + /** + * Callback triggered when a user: + * 1. Manually dismisses a notification {@see ExpandableNotificationRow}. + * 2. Clicks on a notification with flag {@link android.app.Notification#FLAG_AUTO_CANCEL}. + * {@see StatusBarNotificationActivityStarter} + */ @Override public void onDismiss( NotificationEntry entry, @@ -80,4 +89,11 @@ public class OnDismissCallbackImpl implements OnDismissCallback { NotificationLogger.getNotificationLocation(entry))) ); } + + @Override + public void onImportanceChanged(NotificationEntry entry) { + mVisualStabilityCoordinator.temporarilyAllowSectionChanges( + entry, + SystemClock.uptimeMillis()); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java index 1c02c62602cf..db49e4476a99 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.collection.init; import android.util.Log; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationListener; @@ -36,12 +37,11 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import javax.inject.Inject; -import javax.inject.Singleton; /** * Initialization code for the new notification pipeline. */ -@Singleton +@SysUISingleton public class NotifPipelineInitializer implements Dumpable { private final NotifPipeline mPipelineWrapper; private final GroupCoalescer mGroupCoalescer; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnDismissCallbackImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnUserInteractionCallbackImplLegacy.java index 94ffa8f8c5ed..cce8cdc64d30 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnDismissCallbackImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnUserInteractionCallbackImplLegacy.java @@ -27,30 +27,36 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.logging.NotificationLogger; -import com.android.systemui.statusbar.notification.row.OnDismissCallback; +import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback; import com.android.systemui.statusbar.policy.HeadsUpManager; /** - * Callback used when a user: - * 1. Manually dismisses a notification {@see ExpandableNotificationRow}. - * 2. Clicks on a notification with flag {@link android.app.Notification#FLAG_AUTO_CANCEL}. - * {@see StatusBarNotificationActivityStarter} + * Callback for when a user interacts with a {@see ExpandableNotificationRow}. */ -public class OnDismissCallbackImpl implements OnDismissCallback { +public class OnUserInteractionCallbackImplLegacy implements OnUserInteractionCallback { private final NotificationEntryManager mNotificationEntryManager; private final HeadsUpManager mHeadsUpManager; private final StatusBarStateController mStatusBarStateController; + private final VisualStabilityManager mVisualStabilityManager; - public OnDismissCallbackImpl( + public OnUserInteractionCallbackImplLegacy( NotificationEntryManager notificationEntryManager, HeadsUpManager headsUpManager, - StatusBarStateController statusBarStateController + StatusBarStateController statusBarStateController, + VisualStabilityManager visualStabilityManager ) { mNotificationEntryManager = notificationEntryManager; mHeadsUpManager = headsUpManager; mStatusBarStateController = statusBarStateController; + mVisualStabilityManager = visualStabilityManager; } + /** + * Callback triggered when a user: + * 1. Manually dismisses a notification {@see ExpandableNotificationRow}. + * 2. Clicks on a notification with flag {@link android.app.Notification#FLAG_AUTO_CANCEL}. + * {@see StatusBarNotificationActivityStarter} + */ @Override public void onDismiss( NotificationEntry entry, @@ -77,5 +83,10 @@ public class OnDismissCallbackImpl implements OnDismissCallback { cancellationReason ); } + + @Override + public void onImportanceChanged(NotificationEntry entry) { + mVisualStabilityManager.temporarilyAllowReordering(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/VisualStabilityManager.java index 8341c02b6b63..165df30b457d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/VisualStabilityManager.java @@ -11,10 +11,10 @@ * 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 + * limitations under the License. */ -package com.android.systemui.statusbar.notification; +package com.android.systemui.statusbar.notification.collection.legacy; import android.os.Handler; import android.os.SystemClock; @@ -24,7 +24,11 @@ import androidx.collection.ArraySet; import com.android.systemui.Dumpable; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.statusbar.NotificationPresenter; +import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.notification.NotificationEntryListener; +import com.android.systemui.statusbar.notification.NotificationEntryManager; +import com.android.systemui.statusbar.notification.VisibilityLocationProvider; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.dagger.NotificationsModule; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -65,24 +69,44 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl */ public VisualStabilityManager( NotificationEntryManager notificationEntryManager, - @Main Handler handler) { + @Main Handler handler, + StatusBarStateController statusBarStateController, + WakefulnessLifecycle wakefulnessLifecycle) { mHandler = handler; - notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() { - @Override - public void onPreEntryUpdated(NotificationEntry entry) { - final boolean ambientStateHasChanged = - entry.isAmbient() != entry.getRow().isLowPriority(); - if (ambientStateHasChanged) { - // note: entries are removed in onReorderingFinished - mLowPriorityReorderingViews.add(entry); + if (notificationEntryManager != null) { + notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() { + @Override + public void onPreEntryUpdated(NotificationEntry entry) { + final boolean ambientStateHasChanged = + entry.isAmbient() != entry.getRow().isLowPriority(); + if (ambientStateHasChanged) { + // note: entries are removed in onReorderingFinished + mLowPriorityReorderingViews.add(entry); + } } - } - }); - } + }); + } + + if (statusBarStateController != null) { + setPulsing(statusBarStateController.isPulsing()); + statusBarStateController.addCallback(new StatusBarStateController.StateListener() { + @Override + public void onPulsingChanged(boolean pulsing) { + setPulsing(pulsing); + } + + @Override + public void onExpandedChanged(boolean expanded) { + setPanelExpanded(expanded); + } + }); + } - public void setUpWithPresenter(NotificationPresenter presenter) { + if (wakefulnessLifecycle != null) { + wakefulnessLifecycle.addObserver(mWakefulnessObserver); + } } /** @@ -120,25 +144,25 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl } /** - * Set the panel to be expanded. + * @param screenOn whether the screen is on */ - public void setPanelExpanded(boolean expanded) { - mPanelExpanded = expanded; + private void setScreenOn(boolean screenOn) { + mScreenOn = screenOn; updateAllowedStates(); } /** - * @param screenOn whether the screen is on + * Set the panel to be expanded. */ - public void setScreenOn(boolean screenOn) { - mScreenOn = screenOn; + private void setPanelExpanded(boolean expanded) { + mPanelExpanded = expanded; updateAllowedStates(); } /** * @param pulsing whether we are currently pulsing for ambient display. */ - public void setPulsing(boolean pulsing) { + private void setPulsing(boolean pulsing) { if (mPulsing == pulsing) { return; } @@ -215,6 +239,10 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl mVisibilityLocationProvider = visibilityLocationProvider; } + /** + * Notifications have been reordered, so reset all the allowed list of views that are allowed + * to reorder. + */ public void onReorderingFinished() { mAllowedReorderViews.clear(); mAddedChildren.clear(); @@ -271,11 +299,27 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl pw.println(); } + final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() { + @Override + public void onFinishedGoingToSleep() { + setScreenOn(false); + } + + @Override + public void onStartedWakingUp() { + setScreenOn(true); + } + }; + + + /** + * See {@link Callback#onChangeAllowed()} + */ public interface Callback { + /** * Called when changing is allowed again. */ void onChangeAllowed(); } - } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java index f1f7d632b6f8..798bfe7f39d0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java @@ -81,9 +81,10 @@ public class PipelineState { public static final int STATE_PRE_GROUP_FILTERING = 3; public static final int STATE_GROUPING = 4; public static final int STATE_TRANSFORMING = 5; - public static final int STATE_SORTING = 6; - public static final int STATE_FINALIZE_FILTERING = 7; - public static final int STATE_FINALIZING = 8; + public static final int STATE_GROUP_STABILIZING = 6; + public static final int STATE_SORTING = 7; + public static final int STATE_FINALIZE_FILTERING = 8; + public static final int STATE_FINALIZING = 9; @IntDef(prefix = { "STATE_" }, value = { STATE_IDLE, @@ -92,6 +93,7 @@ public class PipelineState { STATE_PRE_GROUP_FILTERING, STATE_GROUPING, STATE_TRANSFORMING, + STATE_GROUP_STABILIZING, STATE_SORTING, STATE_FINALIZE_FILTERING, STATE_FINALIZING, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt index 67f8bfeaf141..f7bfeb7234f0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt @@ -57,6 +57,15 @@ class ShadeListBuilderLogger @Inject constructor( }) } + fun logReorderingAllowedInvalidated(name: String, pipelineState: Int) { + buffer.log(TAG, DEBUG, { + str1 = name + int1 = pipelineState + }, { + """ReorderingNowAllowed "$str1" invalidated; pipeline state is $int1""" + }) + } + fun logPromoterInvalidated(name: String, pipelineState: Int) { buffer.log(TAG, DEBUG, { str1 = name @@ -156,6 +165,21 @@ class ShadeListBuilderLogger @Inject constructor( }) } + fun logParentChangeSuppressed( + buildId: Int, + suppressedParent: GroupEntry?, + keepingParent: GroupEntry? + ) { + buffer.log(TAG, INFO, { + int1 = buildId + str1 = suppressedParent?.key + str2 = keepingParent?.key + }, { + "(Build $long1) Change of parent to '$str1' suppressed; " + + "keeping parent '$str2'" + }) + } + fun logFilterChanged( buildId: Int, prevFilter: NotifFilter?, @@ -206,6 +230,23 @@ class ShadeListBuilderLogger @Inject constructor( }) } + fun logSectionChangeSuppressed( + buildId: Int, + suppressedSection: NotifSection?, + suppressedSectionIndex: Int, + assignedSection: NotifSection? + ) { + buffer.log(TAG, INFO, { + long1 = buildId.toLong() + str1 = suppressedSection?.name + int1 = suppressedSectionIndex + str2 = assignedSection?.name + }, { + "(Build $long1) Section change suppressed: '$str1' (#$int1). " + + "Keeping section: '$str2'" + }) + } + fun logFinalList(entries: List<ListEntry>) { if (entries.isEmpty()) { buffer.log(TAG, DEBUG, {}, { "(empty list)" }) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.java new file mode 100644 index 000000000000..58d4b97f69b5 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.java @@ -0,0 +1,55 @@ +/* + * 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.collection.listbuilder.pluggable; + +import com.android.systemui.statusbar.notification.collection.NotificationEntry; + +/** + * Pluggable for participating in notif stabilization. In particular, suppressing group and + * section changes. + * + * The stability manager should be invalidated when previously suppressed a group or + * section change is now allowed. + */ +public abstract class NotifStabilityManager extends Pluggable<NotifStabilityManager> { + + protected NotifStabilityManager(String name) { + super(name); + } + + /** + * Called at the beginning of every pipeline run to perform any necessary cleanup from the + * previous run. + */ + public abstract void onBeginRun(); + + /** + * Returns whether this notification can currently change groups/parents. + * Per iteration of the notification pipeline, locally stores this information until the next + * run of the pipeline. When this method returns true, it's expected that a group change for + * this entry is being suppressed. + */ + public abstract boolean isGroupChangeAllowed(NotificationEntry entry); + + /** + * Returns whether this notification entry can currently change sections. + * Per iteration of the notification pipeline, locally stores this information until the next + * run of the pipeline. When this method returns true, it's expected that a section change is + * being suppressed. + */ + public abstract boolean isSectionChangeAllowed(NotificationEntry entry); +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java index 1c076c49249b..8b803b517f14 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.collection.provider; import android.app.Notification; import android.app.NotificationManager; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.collection.GroupEntry; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -28,7 +29,6 @@ import com.android.systemui.statusbar.phone.NotificationGroupManager; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * Determines whether a notification is considered 'high priority'. @@ -36,7 +36,7 @@ import javax.inject.Singleton; * Notifications that are high priority are visible on the lock screen/status bar and in the top * section in the shade. */ -@Singleton +@SysUISingleton public class HighPriorityProvider { private final PeopleNotificationIdentifier mPeopleNotificationIdentifier; private final NotificationGroupManager mGroupManager; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt index 00fd09dd662e..79bc3d757ebd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt @@ -17,16 +17,16 @@ package com.android.systemui.statusbar.notification.collection.render import android.view.textclassifier.Log +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController import javax.inject.Inject -import javax.inject.Singleton /** * The ViewBarn is just a map from [ListEntry] to an instance of an * [ExpandableNotificationRowController]. */ -@Singleton +@SysUISingleton class NotifViewBarn @Inject constructor() { private val rowMap = mutableMapOf<String, ExpandableNotificationRowController>() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt index 201be59d80b4..118ff4a9fbb7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt @@ -21,6 +21,7 @@ import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.ShadeListBuilder import com.android.systemui.statusbar.notification.stack.NotificationListContainer +import com.android.systemui.statusbar.phone.NotificationIconAreaController import java.lang.RuntimeException import javax.inject.Inject @@ -31,7 +32,8 @@ import javax.inject.Inject class ShadeViewManager constructor( listContainer: NotificationListContainer, logger: ShadeViewDifferLogger, - private val viewBarn: NotifViewBarn + private val viewBarn: NotifViewBarn, + private val notificationIconAreaController: NotificationIconAreaController ) { private val rootController = RootNodeController(listContainer) private val viewDiffer = ShadeViewDiffer(rootController, logger) @@ -52,6 +54,7 @@ class ShadeViewManager constructor( root.children.add(buildNotifNode(entry, root)) } + notificationIconAreaController.updateNotificationIcons(notifList) return root } @@ -80,9 +83,10 @@ class ShadeViewManager constructor( class ShadeViewManagerFactory @Inject constructor( private val logger: ShadeViewDifferLogger, - private val viewBarn: NotifViewBarn + private val viewBarn: NotifViewBarn, + private val notificationIconAreaController: NotificationIconAreaController ) { fun create(listContainer: NotificationListContainer): ShadeViewManager { - return ShadeViewManager(listContainer, logger, viewBarn) + return ShadeViewManager(listContainer, logger, viewBarn, notificationIconAreaController) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java index 046dc3c8dce6..6d01324f1b7b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java @@ -28,9 +28,11 @@ import com.android.internal.logging.UiEventLogger; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.R; import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.UiBackground; +import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.settings.CurrentUserContextTracker; import com.android.systemui.statusbar.FeatureFlags; @@ -40,14 +42,16 @@ import com.android.systemui.statusbar.notification.AssistantFeedbackController; import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotifCollection; import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationRankingManager; +import com.android.systemui.statusbar.notification.collection.coordinator.VisualStabilityCoordinator; import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder; -import com.android.systemui.statusbar.notification.collection.inflation.OnDismissCallbackImpl; +import com.android.systemui.statusbar.notification.collection.inflation.OnUserInteractionCallbackImpl; +import com.android.systemui.statusbar.notification.collection.legacy.OnUserInteractionCallbackImplLegacy; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; import com.android.systemui.statusbar.notification.init.NotificationsController; @@ -61,7 +65,7 @@ import com.android.systemui.statusbar.notification.logging.NotificationPanelLogg import com.android.systemui.statusbar.notification.row.ChannelEditorDialogController; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; -import com.android.systemui.statusbar.notification.row.OnDismissCallback; +import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback; import com.android.systemui.statusbar.notification.row.PriorityOnboardingDialogController; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.StatusBar; @@ -71,7 +75,6 @@ import com.android.systemui.util.leak.LeakDetector; import java.util.concurrent.Executor; import javax.inject.Provider; -import javax.inject.Singleton; import dagger.Binds; import dagger.Lazy; @@ -84,7 +87,7 @@ import dagger.Provides; @Module public interface NotificationsModule { /** Provides an instance of {@link NotificationEntryManager} */ - @Singleton + @SysUISingleton @Provides static NotificationEntryManager provideNotificationEntryManager( NotificationEntryManagerLogger logger, @@ -111,11 +114,10 @@ public interface NotificationsModule { } /** Provides an instance of {@link NotificationGutsManager} */ - @Singleton + @SysUISingleton @Provides static NotificationGutsManager provideNotificationGutsManager( Context context, - VisualStabilityManager visualStabilityManager, Lazy<StatusBar> statusBarLazy, @Main Handler mainHandler, @Background Handler bgHandler, @@ -129,10 +131,10 @@ public interface NotificationsModule { Provider<PriorityOnboardingDialogController.Builder> builderProvider, AssistantFeedbackController assistantFeedbackController, BubbleController bubbleController, - UiEventLogger uiEventLogger) { + UiEventLogger uiEventLogger, + OnUserInteractionCallback onUserInteractionCallback) { return new NotificationGutsManager( context, - visualStabilityManager, statusBarLazy, mainHandler, bgHandler, @@ -146,19 +148,28 @@ public interface NotificationsModule { builderProvider, assistantFeedbackController, bubbleController, - uiEventLogger); + uiEventLogger, + onUserInteractionCallback); } /** Provides an instance of {@link VisualStabilityManager} */ - @Singleton + @SysUISingleton @Provides static VisualStabilityManager provideVisualStabilityManager( - NotificationEntryManager notificationEntryManager, Handler handler) { - return new VisualStabilityManager(notificationEntryManager, handler); + FeatureFlags featureFlags, + NotificationEntryManager notificationEntryManager, + Handler handler, + StatusBarStateController statusBarStateController, + WakefulnessLifecycle wakefulnessLifecycle) { + return new VisualStabilityManager( + notificationEntryManager, + handler, + statusBarStateController, + wakefulnessLifecycle); } /** Provides an instance of {@link NotificationLogger} */ - @Singleton + @SysUISingleton @Provides static NotificationLogger provideNotificationLogger( NotificationListener notificationListener, @@ -177,14 +188,14 @@ public interface NotificationsModule { } /** Provides an instance of {@link NotificationPanelLogger} */ - @Singleton + @SysUISingleton @Provides static NotificationPanelLogger provideNotificationPanelLogger() { return new NotificationPanelLoggerImpl(); } /** Provides an instance of {@link NotificationBlockingHelperManager} */ - @Singleton + @SysUISingleton @Provides static NotificationBlockingHelperManager provideNotificationBlockingHelperManager( Context context, @@ -196,7 +207,7 @@ public interface NotificationsModule { } /** Initializes the notification data pipeline (can be disabled via config). */ - @Singleton + @SysUISingleton @Provides static NotificationsController provideNotificationsController( Context context, @@ -213,7 +224,7 @@ public interface NotificationsModule { * Provide the active notification collection managing the notifications to render. */ @Provides - @Singleton + @SysUISingleton static CommonNotifCollection provideCommonNotifCollection( FeatureFlags featureFlags, Lazy<NotifPipeline> pipeline, @@ -226,21 +237,28 @@ public interface NotificationsModule { * from the notification shade or it gets auto-cancelled by click. */ @Provides - @Singleton - static OnDismissCallback provideOnDismissCallback( + @SysUISingleton + static OnUserInteractionCallback provideOnUserInteractionCallback( FeatureFlags featureFlags, HeadsUpManager headsUpManager, StatusBarStateController statusBarStateController, Lazy<NotifPipeline> pipeline, Lazy<NotifCollection> notifCollection, - NotificationEntryManager entryManager) { + Lazy<VisualStabilityCoordinator> visualStabilityCoordinator, + NotificationEntryManager entryManager, + VisualStabilityManager visualStabilityManager) { return featureFlags.isNewNotifPipelineRenderingEnabled() - ? new OnDismissCallbackImpl( - pipeline.get(), notifCollection.get(), headsUpManager, - statusBarStateController) - : new com.android.systemui.statusbar.notification.collection - .legacy.OnDismissCallbackImpl( - entryManager, headsUpManager, statusBarStateController); + ? new OnUserInteractionCallbackImpl( + pipeline.get(), + notifCollection.get(), + headsUpManager, + statusBarStateController, + visualStabilityCoordinator.get()) + : new OnUserInteractionCallbackImplLegacy( + entryManager, + headsUpManager, + statusBarStateController, + visualStabilityManager); } /** */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt index 6e4fcd5f97b1..6460892952e7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.init import android.service.notification.StatusBarNotification +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption import com.android.systemui.statusbar.FeatureFlags import com.android.systemui.statusbar.NotificationListener @@ -26,10 +27,11 @@ import com.android.systemui.statusbar.notification.NotificationClicker import com.android.systemui.statusbar.notification.NotificationEntryManager import com.android.systemui.statusbar.notification.NotificationListController import com.android.systemui.statusbar.notification.collection.NotifPipeline +import com.android.systemui.statusbar.notification.collection.TargetSdkResolver import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer -import com.android.systemui.statusbar.notification.collection.TargetSdkResolver import com.android.systemui.statusbar.notification.interruption.HeadsUpController +import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder import com.android.systemui.statusbar.notification.row.NotifBindPipelineInitializer import com.android.systemui.statusbar.notification.stack.NotificationListContainer import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper @@ -37,14 +39,12 @@ import com.android.systemui.statusbar.phone.NotificationGroupManager import com.android.systemui.statusbar.phone.StatusBar import com.android.systemui.statusbar.policy.DeviceProvisionedController import com.android.systemui.statusbar.policy.HeadsUpManager -import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder import com.android.systemui.statusbar.policy.RemoteInputUriController import dagger.Lazy import java.io.FileDescriptor import java.io.PrintWriter import java.util.Optional import javax.inject.Inject -import javax.inject.Singleton /** * Master controller for all notifications-related work @@ -53,7 +53,7 @@ import javax.inject.Singleton * Once we migrate away from the need for such things, this class becomes primarily a place to do * any initialization work that notifications require. */ -@Singleton +@SysUISingleton class NotificationsControllerImpl @Inject constructor( private val featureFlags: FeatureFlags, private val notificationListener: NotificationListener, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/BypassHeadsUpNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/BypassHeadsUpNotifier.kt index 0fd865b603f8..f8d6c6d8ec10 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/BypassHeadsUpNotifier.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/BypassHeadsUpNotifier.kt @@ -20,6 +20,7 @@ import android.content.Context import android.media.MediaMetadata import android.provider.Settings import com.android.keyguard.KeyguardUpdateMonitor +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.NotificationMediaManager @@ -30,13 +31,12 @@ import com.android.systemui.statusbar.phone.HeadsUpManagerPhone import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.tuner.TunerService import javax.inject.Inject -import javax.inject.Singleton /** * A class that automatically creates heads up for important notification when bypassing the * lockscreen */ -@Singleton +@SysUISingleton class BypassHeadsUpNotifier @Inject constructor( private val context: Context, private val bypassController: KeyguardBypassController, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpController.java index 9b6ae9a7f99d..4d56e6013d71 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpController.java @@ -24,25 +24,25 @@ import android.util.Log; import androidx.annotation.NonNull; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controller class for old pipeline heads up logic. It listens to {@link NotificationEntryManager} * entry events and appropriately binds or unbinds the heads up view and promotes it to the top * of the screen. */ -@Singleton +@SysUISingleton public class HeadsUpController { private final HeadsUpViewBinder mHeadsUpViewBinder; private final NotificationInterruptStateProvider mInterruptStateProvider; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinder.java index ff139957031a..ffec3671995f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinder.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinder.java @@ -24,6 +24,7 @@ import androidx.annotation.Nullable; import androidx.core.os.CancellationSignal; import com.android.internal.util.NotificationMessagingUtil; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.coordinator.HeadsUpCoordinator; @@ -34,7 +35,6 @@ import com.android.systemui.statusbar.notification.row.RowContentBindStage; import java.util.Map; import javax.inject.Inject; -import javax.inject.Singleton; /** * Wrapper around heads up view binding logic. {@link HeadsUpViewBinder} is responsible for @@ -44,7 +44,7 @@ import javax.inject.Singleton; * TODO: This should be moved into {@link HeadsUpCoordinator} when the old pipeline is deprecated * (i.e. when {@link HeadsUpController} is removed). */ -@Singleton +@SysUISingleton public class HeadsUpViewBinder { private final RowContentBindStage mStage; private final NotificationMessagingUtil mNotificationMessagingUtil; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java index 71f6dac4e234..433d5e19ed6b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java @@ -32,6 +32,7 @@ import android.service.notification.StatusBarNotification; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.StatusBarState; @@ -44,12 +45,11 @@ import java.util.ArrayList; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * Provides heads-up and pulsing state for notification entries. */ -@Singleton +@SysUISingleton public class NotificationInterruptStateProviderImpl implements NotificationInterruptStateProvider { private static final String TAG = "InterruptionStateProvider"; private static final boolean DEBUG = true; //false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt index d32d09dff630..743bf332fc9d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt @@ -35,6 +35,7 @@ import com.android.internal.statusbar.NotificationVisibility import com.android.internal.widget.MessagingGroup import com.android.settingslib.notification.ConversationIconFactory import com.android.systemui.R +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.NotificationPersonExtractorPlugin @@ -48,7 +49,6 @@ import com.android.systemui.statusbar.policy.ExtensionController import java.util.ArrayDeque import java.util.concurrent.Executor import javax.inject.Inject -import javax.inject.Singleton private const val MAX_STORED_INACTIVE_PEOPLE = 10 @@ -58,7 +58,7 @@ interface NotificationPersonExtractor { fun isPersonNotification(sbn: StatusBarNotification): Boolean } -@Singleton +@SysUISingleton class NotificationPersonExtractorPluginBoundary @Inject constructor( extensionController: ExtensionController ) : NotificationPersonExtractor { @@ -87,7 +87,7 @@ class NotificationPersonExtractorPluginBoundary @Inject constructor( plugin?.isPersonNotification(sbn) ?: false } -@Singleton +@SysUISingleton class PeopleHubDataSourceImpl @Inject constructor( private val notificationEntryManager: NotificationEntryManager, private val extractor: NotificationPersonExtractor, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt index 7f42fe0473f3..55bd77fdab68 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt @@ -23,10 +23,10 @@ import android.os.Handler import android.os.UserHandle import android.provider.Settings import android.view.View +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.ActivityStarter import javax.inject.Inject -import javax.inject.Singleton /** Boundary between the View and PeopleHub, as seen by the View. */ interface PeopleHubViewAdapter { @@ -68,7 +68,7 @@ interface PeopleHubViewModelFactory { * * @param dataSource PeopleHub data pipeline. */ -@Singleton +@SysUISingleton class PeopleHubViewAdapterImpl @Inject constructor( private val dataSource: DataSource<@JvmSuppressWildcards PeopleHubViewModelFactory> ) : PeopleHubViewAdapter { @@ -99,7 +99,7 @@ private class PeopleHubDataListenerImpl( * This class serves as the glue between the View layer (which depends on * [PeopleHubViewBoundary]) and the Data layer (which produces [PeopleHubModel]s). */ -@Singleton +@SysUISingleton class PeopleHubViewModelFactoryDataSourceImpl @Inject constructor( private val activityStarter: ActivityStarter, private val dataSource: DataSource<@JvmSuppressWildcards PeopleHubModel> @@ -151,7 +151,7 @@ private class PeopleHubViewModelFactoryImpl( } } -@Singleton +@SysUISingleton class PeopleHubSettingChangeDataSourceImpl @Inject constructor( @Main private val handler: Handler, context: Context diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt index d36627fb849d..1ac2cb5a36d5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.people import android.annotation.IntDef import android.service.notification.NotificationListenerService.Ranking import android.service.notification.StatusBarNotification +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.PeopleNotificationType import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_FULL_PERSON import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_IMPORTANT_PERSON @@ -26,7 +27,6 @@ import com.android.systemui.statusbar.notification.people.PeopleNotificationIden import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_PERSON import com.android.systemui.statusbar.phone.NotificationGroupManager import javax.inject.Inject -import javax.inject.Singleton import kotlin.math.max interface PeopleNotificationIdentifier { @@ -59,7 +59,7 @@ interface PeopleNotificationIdentifier { } } -@Singleton +@SysUISingleton class PeopleNotificationIdentifierImpl @Inject constructor( private val personExtractor: NotificationPersonExtractor, private val groupManager: NotificationGroupManager diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java deleted file mode 100644 index 28c53dc6d9b2..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java +++ /dev/null @@ -1,214 +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.systemui.statusbar.notification.row; - -import android.app.AppOpsManager; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.graphics.drawable.Drawable; -import android.service.notification.StatusBarNotification; -import android.util.ArraySet; -import android.util.AttributeSet; -import android.view.View; -import android.view.accessibility.AccessibilityEvent; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.android.internal.logging.MetricsLogger; -import com.android.internal.logging.UiEventLogger; -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.systemui.R; - -/** - * The guts of a notification revealed when performing a long press. - */ -public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsContent { - private static final String TAG = "AppOpsGuts"; - - private PackageManager mPm; - - private String mPkg; - private String mAppName; - private int mAppUid; - private StatusBarNotification mSbn; - private ArraySet<Integer> mAppOps; - private MetricsLogger mMetricsLogger; - private OnSettingsClickListener mOnSettingsClickListener; - private NotificationGuts mGutsContainer; - private UiEventLogger mUiEventLogger; - - private OnClickListener mOnOk = v -> { - mGutsContainer.closeControls(v, false); - }; - - public AppOpsInfo(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public interface OnSettingsClickListener { - void onClick(View v, String pkg, int uid, ArraySet<Integer> ops); - } - - public void bindGuts(final PackageManager pm, - final OnSettingsClickListener onSettingsClick, - final StatusBarNotification sbn, - final UiEventLogger uiEventLogger, - ArraySet<Integer> activeOps) { - mPkg = sbn.getPackageName(); - mSbn = sbn; - mPm = pm; - mAppName = mPkg; - mOnSettingsClickListener = onSettingsClick; - mAppOps = activeOps; - mUiEventLogger = uiEventLogger; - - bindHeader(); - bindPrompt(); - bindButtons(); - - logUiEvent(NotificationAppOpsEvent.NOTIFICATION_APP_OPS_OPEN); - mMetricsLogger = new MetricsLogger(); - mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, true); - } - - private void bindHeader() { - // Package name - Drawable pkgicon = null; - ApplicationInfo info; - try { - info = mPm.getApplicationInfo(mPkg, - PackageManager.MATCH_UNINSTALLED_PACKAGES - | PackageManager.MATCH_DISABLED_COMPONENTS - | PackageManager.MATCH_DIRECT_BOOT_UNAWARE - | PackageManager.MATCH_DIRECT_BOOT_AWARE); - if (info != null) { - mAppUid = mSbn.getUid(); - mAppName = String.valueOf(mPm.getApplicationLabel(info)); - pkgicon = mPm.getApplicationIcon(info); - } - } catch (PackageManager.NameNotFoundException e) { - // app is gone, just show package name and generic icon - pkgicon = mPm.getDefaultActivityIcon(); - } - ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon); - ((TextView) findViewById(R.id.pkgname)).setText(mAppName); - } - - private void bindPrompt() { - final TextView prompt = findViewById(R.id.prompt); - prompt.setText(getPrompt()); - } - - private void bindButtons() { - View settings = findViewById(R.id.settings); - settings.setOnClickListener((View view) -> { - mOnSettingsClickListener.onClick(view, mPkg, mAppUid, mAppOps); - }); - TextView ok = findViewById(R.id.ok); - ok.setOnClickListener(mOnOk); - ok.setAccessibilityDelegate(mGutsContainer.getAccessibilityDelegate()); - } - - private String getPrompt() { - if (mAppOps == null || mAppOps.size() == 0) { - return ""; - } else if (mAppOps.size() == 1) { - if (mAppOps.contains(AppOpsManager.OP_CAMERA)) { - return mContext.getString(R.string.appops_camera); - } else if (mAppOps.contains(AppOpsManager.OP_RECORD_AUDIO)) { - return mContext.getString(R.string.appops_microphone); - } else { - return mContext.getString(R.string.appops_overlay); - } - } else if (mAppOps.size() == 2) { - if (mAppOps.contains(AppOpsManager.OP_CAMERA)) { - if (mAppOps.contains(AppOpsManager.OP_RECORD_AUDIO)) { - return mContext.getString(R.string.appops_camera_mic); - } else { - return mContext.getString(R.string.appops_camera_overlay); - } - } else { - return mContext.getString(R.string.appops_mic_overlay); - } - } else { - return mContext.getString(R.string.appops_camera_mic_overlay); - } - } - - @Override - public void onInitializeAccessibilityEvent(AccessibilityEvent event) { - super.onInitializeAccessibilityEvent(event); - if (mGutsContainer != null && - event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { - if (mGutsContainer.isExposed()) { - event.getText().add(mContext.getString( - R.string.notification_channel_controls_opened_accessibility, mAppName)); - } else { - event.getText().add(mContext.getString( - R.string.notification_channel_controls_closed_accessibility, mAppName)); - } - } - } - - @Override - public void setGutsParent(NotificationGuts guts) { - mGutsContainer = guts; - } - - @Override - public boolean willBeRemoved() { - return false; - } - - @Override - public boolean shouldBeSaved() { - return false; - } - - @Override - public boolean needsFalsingProtection() { - return false; - } - - @Override - public View getContentView() { - return this; - } - - @Override - public boolean handleCloseControls(boolean save, boolean force) { - logUiEvent(NotificationAppOpsEvent.NOTIFICATION_APP_OPS_CLOSE); - if (mMetricsLogger != null) { - mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, false); - } - return false; - } - - @Override - public int getActualHeight() { - return getHeight(); - } - - private void logUiEvent(NotificationAppOpsEvent event) { - if (mSbn != null) { - mUiEventLogger.logWithInstanceId(event, - mSbn.getUid(), mSbn.getPackageName(), mSbn.getInstanceId()); - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt index 93db9cdf85ef..9bba7effd824 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt @@ -37,12 +37,10 @@ import android.view.Window import android.view.WindowInsets.Type.statusBars import android.view.WindowManager import android.widget.TextView - import com.android.internal.annotations.VisibleForTesting import com.android.systemui.R - +import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject -import javax.inject.Singleton private const val TAG = "ChannelDialogController" @@ -58,7 +56,7 @@ private const val TAG = "ChannelDialogController" * - the next 3 channels sorted alphabetically for that app <on/off> * - <on/off> */ -@Singleton +@SysUISingleton class ChannelEditorDialogController @Inject constructor( c: Context, private val noMan: INotificationManager, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index 22d0357b14c2..9c09cba5e137 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -84,8 +84,8 @@ import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.notification.AboveShelfChangedListener; import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.NotificationUtils; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.logging.NotificationCounters; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; @@ -239,7 +239,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private boolean mShowNoBackground; private ExpandableNotificationRow mNotificationParent; private OnExpandClickListener mOnExpandClickListener; - private View.OnClickListener mOnAppOpsClickListener; + private View.OnClickListener mOnAppClickListener; private View.OnClickListener mOnFeedbackClickListener; // Listener will be called when receiving a long click event. @@ -323,7 +323,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private View mGroupParentWhenDismissed; private boolean mShelfIconVisible; private boolean mAboveShelf; - private OnDismissCallback mOnDismissCallback; + private OnUserInteractionCallback mOnUserInteractionCallback; private boolean mIsLowPriority; private boolean mIsColorized; private boolean mUseIncreasedCollapsedHeight; @@ -1139,7 +1139,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView items.add(NotificationMenuRow.createPartialConversationItem(mContext)); items.add(NotificationMenuRow.createInfoItem(mContext)); items.add(NotificationMenuRow.createSnoozeItem(mContext)); - items.add(NotificationMenuRow.createAppOpsItem(mContext)); mMenuRow.setMenuItems(items); } if (existed) { @@ -1446,8 +1445,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } dismiss(fromAccessibility); if (mEntry.isClearable()) { - if (mOnDismissCallback != null) { - mOnDismissCallback.onDismiss(mEntry, REASON_CANCEL); + if (mOnUserInteractionCallback != null) { + mOnUserInteractionCallback.onDismiss(mEntry, REASON_CANCEL); } } } @@ -1464,10 +1463,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView return mIsBlockingHelperShowing && mNotificationTranslationFinished; } - void setOnDismissCallback(OnDismissCallback onDismissCallback) { - mOnDismissCallback = onDismissCallback; - } - @Override public View getShelfTransformationTarget() { if (mIsSummaryWithChildren && !shouldShowPublic()) { @@ -1598,11 +1593,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView RowContentBindStage rowContentBindStage, OnExpandClickListener onExpandClickListener, NotificationMediaManager notificationMediaManager, - CoordinateOnClickListener onAppOpsClickListener, CoordinateOnClickListener onFeedbackClickListener, FalsingManager falsingManager, StatusBarStateController statusBarStateController, - PeopleNotificationIdentifier peopleNotificationIdentifier) { + PeopleNotificationIdentifier peopleNotificationIdentifier, + OnUserInteractionCallback onUserInteractionCallback) { mAppName = appName; if (mMenuRow == null) { mMenuRow = new NotificationMenuRow(mContext, peopleNotificationIdentifier); @@ -1619,7 +1614,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mRowContentBindStage = rowContentBindStage; mOnExpandClickListener = onExpandClickListener; mMediaManager = notificationMediaManager; - setAppOpsOnClickListener(onAppOpsClickListener); setOnFeedbackClickListener(onFeedbackClickListener); mFalsingManager = falsingManager; mStatusbarStateController = statusBarStateController; @@ -1627,6 +1621,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView for (NotificationContentView l : mLayouts) { l.setPeopleNotificationIdentifier(mPeopleNotificationIdentifier); } + mOnUserInteractionCallback = onUserInteractionCallback; } private void initDimens() { @@ -1677,14 +1672,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView requestLayout(); } - public void showAppOpsIcons(ArraySet<Integer> activeOps) { - if (mIsSummaryWithChildren) { - mChildrenContainer.showAppOpsIcons(activeOps); - } - mPrivateLayout.showAppOpsIcons(activeOps); - mPublicLayout.showAppOpsIcons(activeOps); - } - public void showFeedbackIcon(boolean show) { if (mIsSummaryWithChildren) { mChildrenContainer.showFeedbackIcon(show); @@ -1721,24 +1708,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mPublicLayout.setRecentlyAudiblyAlerted(audiblyAlertedRecently); } - public View.OnClickListener getAppOpsOnClickListener() { - return mOnAppOpsClickListener; - } - - void setAppOpsOnClickListener(CoordinateOnClickListener l) { - mOnAppOpsClickListener = v -> { - createMenu(); - NotificationMenuRowPlugin provider = getProvider(); - if (provider == null) { - return; - } - MenuItem menuItem = provider.getAppOpsMenuItem(mContext); - if (menuItem != null) { - l.onClick(this, v.getWidth() / 2, v.getHeight() / 2, menuItem); - } - }; - } - public View.OnClickListener getFeedbackOnClickListener() { return mOnFeedbackClickListener; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java index 1dbec6603f16..f8bc2bebf93b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java @@ -69,10 +69,9 @@ public class ExpandableNotificationRowController implements NodeController { private final ExpandableNotificationRow.ExpansionLogger mExpansionLogger = this::logNotificationExpansion; - private final ExpandableNotificationRow.CoordinateOnClickListener mOnAppOpsClickListener; private final ExpandableNotificationRow.CoordinateOnClickListener mOnFeedbackClickListener; private final NotificationGutsManager mNotificationGutsManager; - private final OnDismissCallback mOnDismissCallback; + private final OnUserInteractionCallback mOnUserInteractionCallback; private final FalsingManager mFalsingManager; private final boolean mAllowLongPress; private final PeopleNotificationIdentifier mPeopleNotificationIdentifier; @@ -91,7 +90,7 @@ public class ExpandableNotificationRowController implements NodeController { StatusBarStateController statusBarStateController, NotificationGutsManager notificationGutsManager, @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress, - OnDismissCallback onDismissCallback, FalsingManager falsingManager, + OnUserInteractionCallback onUserInteractionCallback, FalsingManager falsingManager, PeopleNotificationIdentifier peopleNotificationIdentifier) { mView = view; mListContainer = listContainer; @@ -109,8 +108,7 @@ public class ExpandableNotificationRowController implements NodeController { mOnExpandClickListener = onExpandClickListener; mStatusBarStateController = statusBarStateController; mNotificationGutsManager = notificationGutsManager; - mOnDismissCallback = onDismissCallback; - mOnAppOpsClickListener = mNotificationGutsManager::openGuts; + mOnUserInteractionCallback = onUserInteractionCallback; mOnFeedbackClickListener = mNotificationGutsManager::openGuts; mAllowLongPress = allowLongPress; mFalsingManager = falsingManager; @@ -132,13 +130,12 @@ public class ExpandableNotificationRowController implements NodeController { mRowContentBindStage, mOnExpandClickListener, mMediaManager, - mOnAppOpsClickListener, mOnFeedbackClickListener, mFalsingManager, mStatusBarStateController, - mPeopleNotificationIdentifier + mPeopleNotificationIdentifier, + mOnUserInteractionCallback ); - mView.setOnDismissCallback(mOnDismissCallback); mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); if (mAllowLongPress) { mView.setLongPressListener((v, x, y, item) -> { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipeline.java index 90d30dcf38ab..f693ebbb7830 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipeline.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipeline.java @@ -28,6 +28,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.os.CancellationSignal; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder; @@ -41,7 +42,6 @@ import java.util.Map; import java.util.Set; import javax.inject.Inject; -import javax.inject.Singleton; /** * {@link NotifBindPipeline} is responsible for converting notifications from their data form to @@ -77,7 +77,7 @@ import javax.inject.Singleton; * views and assumes that a row is given to it when it's inflated. */ @MainThread -@Singleton +@SysUISingleton public final class NotifBindPipeline { private final Map<NotificationEntry, BindEntry> mBindEntries = new ArrayMap<>(); private final NotifBindPipelineLogger mLogger; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifInflationErrorManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifInflationErrorManager.java index a3ca08432745..51eb9f7220fc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifInflationErrorManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifInflationErrorManager.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.row; import androidx.annotation.NonNull; import androidx.collection.ArraySet; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import java.util.ArrayList; @@ -26,14 +27,13 @@ import java.util.List; import java.util.Set; import javax.inject.Inject; -import javax.inject.Singleton; /** * A manager handling the error state of a notification when it encounters an exception while * inflating. We don't want to show these notifications to the user but may want to keep them * around for logging purposes. */ -@Singleton +@SysUISingleton public class NotifInflationErrorManager { Set<NotificationEntry> mErroredNotifs = new ArraySet<>(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java index a7d83b3b2774..9bcac1163acc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java @@ -36,6 +36,7 @@ import android.widget.RemoteViews; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.ImageMessageConsumer; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.media.MediaDataManagerKt; import com.android.systemui.media.MediaFeatureFlag; @@ -58,7 +59,6 @@ import java.util.HashMap; import java.util.concurrent.Executor; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; @@ -66,7 +66,7 @@ import dagger.Lazy; * {@link NotificationContentInflater} binds content to a {@link ExpandableNotificationRow} by * asynchronously building the content's {@link RemoteViews} and applying it to the row. */ -@Singleton +@SysUISingleton @VisibleForTesting(visibility = PACKAGE) public class NotificationContentInflater implements NotificationRowContentBinder { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index 2986b9b75b98..c7e44c5e8e0a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -1568,18 +1568,6 @@ public class NotificationContentView extends FrameLayout { return header; } - public void showAppOpsIcons(ArraySet<Integer> activeOps) { - if (mContractedChild != null) { - mContractedWrapper.showAppOpsIcons(activeOps); - } - if (mExpandedChild != null) { - mExpandedWrapper.showAppOpsIcons(activeOps); - } - if (mHeadsUpChild != null) { - mHeadsUpWrapper.showAppOpsIcons(activeOps); - } - } - public void showFeedbackIcon(boolean show) { if (mContractedChild != null) { mContractedWrapper.showFeedbackIcon(show); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java index f543db74d91a..7c7bb5c83762 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java @@ -69,7 +69,6 @@ import com.android.systemui.bubbles.BubbleController; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.notification.NotificationChannelHelper; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.stack.StackStateAnimator; @@ -89,7 +88,7 @@ public class NotificationConversationInfo extends LinearLayout implements private ShortcutManager mShortcutManager; private PackageManager mPm; private ConversationIconFactory mIconFactory; - private VisualStabilityManager mVisualStabilityManager; + private OnUserInteractionCallback mOnUserInteractionCallback; private Handler mMainHandler; private Handler mBgHandler; private BubbleController mBubbleController; @@ -207,7 +206,7 @@ public class NotificationConversationInfo extends LinearLayout implements ShortcutManager shortcutManager, PackageManager pm, INotificationManager iNotificationManager, - VisualStabilityManager visualStabilityManager, + OnUserInteractionCallback onUserInteractionCallback, String pkg, NotificationChannel notificationChannel, NotificationEntry entry, @@ -224,7 +223,7 @@ public class NotificationConversationInfo extends LinearLayout implements BubbleController bubbleController) { mSelectedAction = -1; mINotificationManager = iNotificationManager; - mVisualStabilityManager = visualStabilityManager; + mOnUserInteractionCallback = onUserInteractionCallback; mPackageName = pkg; mEntry = entry; mSbn = entry.getSbn(); @@ -513,7 +512,7 @@ public class NotificationConversationInfo extends LinearLayout implements mAppUid, mSelectedAction, mNotificationChannel)); mEntry.markForUserTriggeredMovement(true); mMainHandler.postDelayed( - mVisualStabilityManager::temporarilyAllowReordering, + () -> mOnUserInteractionCallback.onImportanceChanged(mEntry), StackStateAnimator.ANIMATION_DURATION_STANDARD); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java index 729b131ac553..60074f608969 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java @@ -60,7 +60,6 @@ import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.StatusBarStateControllerImpl; import com.android.systemui.statusbar.notification.AssistantFeedbackController; import com.android.systemui.statusbar.notification.NotificationActivityStarter; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; import com.android.systemui.statusbar.notification.dagger.NotificationsModule; @@ -88,10 +87,10 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); private final Context mContext; - private final VisualStabilityManager mVisualStabilityManager; private final AccessibilityManager mAccessibilityManager; private final HighPriorityProvider mHighPriorityProvider; private final ChannelEditorDialogController mChannelEditorDialogController; + private final OnUserInteractionCallback mOnUserInteractionCallback; // Dependencies: private final NotificationLockscreenUserManager mLockscreenUserManager = @@ -129,8 +128,10 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx /** * Injected constructor. See {@link NotificationsModule}. */ - public NotificationGutsManager(Context context, VisualStabilityManager visualStabilityManager, - Lazy<StatusBar> statusBarLazy, @Main Handler mainHandler, @Background Handler bgHandler, + public NotificationGutsManager(Context context, + Lazy<StatusBar> statusBarLazy, + @Main Handler mainHandler, + @Background Handler bgHandler, AccessibilityManager accessibilityManager, HighPriorityProvider highPriorityProvider, INotificationManager notificationManager, @@ -141,9 +142,9 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx Provider<PriorityOnboardingDialogController.Builder> builderProvider, AssistantFeedbackController assistantFeedbackController, BubbleController bubbleController, - UiEventLogger uiEventLogger) { + UiEventLogger uiEventLogger, + OnUserInteractionCallback onUserInteractionCallback) { mContext = context; - mVisualStabilityManager = visualStabilityManager; mStatusBarLazy = statusBarLazy; mMainHandler = mainHandler; mBgHandler = bgHandler; @@ -158,6 +159,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx mAssistantFeedbackController = assistantFeedbackController; mBubbleController = bubbleController; mUiEventLogger = uiEventLogger; + mOnUserInteractionCallback = onUserInteractionCallback; } public void setUpWithPresenter(NotificationPresenter presenter, @@ -268,8 +270,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx try { if (gutsView instanceof NotificationSnooze) { initializeSnoozeView(row, (NotificationSnooze) gutsView); - } else if (gutsView instanceof AppOpsInfo) { - initializeAppOpsInfo(row, (AppOpsInfo) gutsView); } else if (gutsView instanceof NotificationInfo) { initializeNotificationInfo(row, (NotificationInfo) gutsView); } else if (gutsView instanceof NotificationConversationInfo) { @@ -309,36 +309,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx } /** - * Sets up the {@link AppOpsInfo} inside the notification row's guts. - * - * @param row view to set up the guts for - * @param appOpsInfoView view to set up/bind within {@code row} - */ - private void initializeAppOpsInfo( - final ExpandableNotificationRow row, - AppOpsInfo appOpsInfoView) { - NotificationGuts guts = row.getGuts(); - StatusBarNotification sbn = row.getEntry().getSbn(); - UserHandle userHandle = sbn.getUser(); - PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext, - userHandle.getIdentifier()); - - AppOpsInfo.OnSettingsClickListener onSettingsClick = - (View v, String pkg, int uid, ArraySet<Integer> ops) -> { - mUiEventLogger.logWithInstanceId( - NotificationAppOpsEvent.NOTIFICATION_APP_OPS_SETTINGS_CLICK, - sbn.getUid(), sbn.getPackageName(), sbn.getInstanceId()); - mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_OPS_GUTS_SETTINGS); - guts.resetFalsingCheck(); - startAppOpsSettingsActivity(pkg, uid, ops, row); - }; - if (!row.getEntry().mActiveAppOps.isEmpty()) { - appOpsInfoView.bindGuts(pmUser, onSettingsClick, sbn, mUiEventLogger, - row.getEntry().mActiveAppOps); - } - } - - /** * Sets up the {@link FeedbackInfo} inside the notification row's guts. * * @param row view to set up the guts for @@ -395,7 +365,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx notificationInfoView.bindNotification( pmUser, mNotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, packageName, row.getEntry().getChannel(), @@ -506,7 +476,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx mShortcutManager, pmUser, mNotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, packageName, entry.getChannel(), entry, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java index a6ba85fc8bdf..7a976ac82223 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java @@ -60,7 +60,6 @@ import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.Dependency; import com.android.systemui.R; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import java.lang.annotation.Retention; @@ -93,9 +92,9 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G private TextView mAutomaticDescriptionView; private INotificationManager mINotificationManager; + private OnUserInteractionCallback mOnUserInteractionCallback; private PackageManager mPm; private MetricsLogger mMetricsLogger; - private VisualStabilityManager mVisualStabilityManager; private ChannelEditorDialogController mChannelEditorDialogController; private String mPackageName; @@ -119,6 +118,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G private boolean mIsAutomaticChosen; private boolean mIsSingleDefaultChannel; private boolean mIsNonblockable; + private NotificationEntry mEntry; private StatusBarNotification mSbn; private boolean mIsDeviceProvisioned; @@ -188,7 +188,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G public void bindNotification( PackageManager pm, INotificationManager iNotificationManager, - VisualStabilityManager visualStabilityManager, + OnUserInteractionCallback onUserInteractionCallback, ChannelEditorDialogController channelEditorDialogController, String pkg, NotificationChannel notificationChannel, @@ -204,11 +204,12 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G throws RemoteException { mINotificationManager = iNotificationManager; mMetricsLogger = Dependency.get(MetricsLogger.class); - mVisualStabilityManager = visualStabilityManager; + mOnUserInteractionCallback = onUserInteractionCallback; mChannelEditorDialogController = channelEditorDialogController; mPackageName = pkg; mUniqueChannelsInRow = uniqueChannelsInRow; mNumUniqueChannelsInRow = uniqueChannelsInRow.size(); + mEntry = entry; mSbn = entry.getSbn(); mPm = pm; mAppSettingsClickListener = onAppSettingsClick; @@ -438,7 +439,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G new UpdateImportanceRunnable(mINotificationManager, mPackageName, mAppUid, mNumUniqueChannelsInRow == 1 ? mSingleNotificationChannel : null, mStartingChannelImportance, newImportance, mIsAutomaticChosen)); - mVisualStabilityManager.temporarilyAllowReordering(); + mOnUserInteractionCallback.onImportanceChanged(mEntry); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java index d264af94947d..205cecc92e55 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java @@ -76,7 +76,6 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl private Context mContext; private FrameLayout mMenuContainer; private NotificationMenuItem mInfoItem; - private MenuItem mAppOpsItem; private MenuItem mFeedbackItem; private MenuItem mSnoozeItem; private ArrayList<MenuItem> mLeftMenuItems; @@ -138,11 +137,6 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl } @Override - public MenuItem getAppOpsMenuItem(Context context) { - return mAppOpsItem; - } - - @Override public MenuItem getFeedbackMenuItem(Context context) { return mFeedbackItem; } @@ -264,7 +258,6 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl // Only show snooze for non-foreground notifications, and if the setting is on mSnoozeItem = createSnoozeItem(mContext); } - mAppOpsItem = createAppOpsItem(mContext); mFeedbackItem = createFeedbackItem(mContext); NotificationEntry entry = mParent.getEntry(); int personNotifType = mPeopleNotificationIdentifier @@ -281,7 +274,6 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl mRightMenuItems.add(mSnoozeItem); } mRightMenuItems.add(mInfoItem); - mRightMenuItems.add(mAppOpsItem); mRightMenuItems.add(mFeedbackItem); mLeftMenuItems.addAll(mRightMenuItems); @@ -690,14 +682,6 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl R.drawable.ic_settings); } - static MenuItem createAppOpsItem(Context context) { - AppOpsInfo appOpsContent = (AppOpsInfo) LayoutInflater.from(context).inflate( - R.layout.app_ops_info, null, false); - MenuItem info = new NotificationMenuItem(context, null, appOpsContent, - -1 /*don't show in slow swipe menu */); - return info; - } - static MenuItem createFeedbackItem(Context context) { FeedbackInfo feedbackContent = (FeedbackInfo) LayoutInflater.from(context).inflate( R.layout.feedback_info, null, false); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowModule.java index df8653cf2406..111b5756b6e8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowModule.java @@ -16,7 +16,7 @@ package com.android.systemui.statusbar.notification.row; -import javax.inject.Singleton; +import com.android.systemui.dagger.SysUISingleton; import dagger.Binds; import dagger.Module; @@ -30,7 +30,7 @@ public abstract class NotificationRowModule { * Provides notification row content binder instance. */ @Binds - @Singleton + @SysUISingleton public abstract NotificationRowContentBinder provideNotificationRowContentBinder( NotificationContentInflater contentBinderImpl); @@ -38,7 +38,7 @@ public abstract class NotificationRowModule { * Provides notification remote view cache instance. */ @Binds - @Singleton + @SysUISingleton public abstract NotifRemoteViewCache provideNotifRemoteViewCache( NotifRemoteViewCacheImpl cacheImpl); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnDismissCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnUserInteractionCallback.java index f1aed899e060..0c3f553825d0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnDismissCallback.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnUserInteractionCallback.java @@ -21,15 +21,21 @@ import android.service.notification.NotificationListenerService; import com.android.systemui.statusbar.notification.collection.NotificationEntry; /** - * Callback when a user clicks on an auto-cancelled notification or manually swipes to dismiss the - * notification. + * Callbacks for when a user interacts with an {@link ExpandableNotificationRow}. */ -public interface OnDismissCallback { +public interface OnUserInteractionCallback { /** - * Handle a user interaction that triggers a notification dismissal. + * Handle a user interaction that triggers a notification dismissal. Called when a user clicks + * on an auto-cancelled notification or manually swipes to dismiss the notification. */ void onDismiss( NotificationEntry entry, @NotificationListenerService.NotificationCancelReason int cancellationReason); + + /** + * Triggered after a user has changed the importance of the notification via its + * {@link NotificationGuts}. + */ + void onImportanceChanged(NotificationEntry entry); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java index c6f0a135cd34..3616f8faee1e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java @@ -20,13 +20,13 @@ import static com.android.systemui.statusbar.notification.row.NotificationRowCon import androidx.annotation.NonNull; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.BindParams; import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback; import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; import javax.inject.Inject; -import javax.inject.Singleton; /** * A stage that binds all content views for an already inflated {@link ExpandableNotificationRow}. @@ -34,7 +34,7 @@ import javax.inject.Singleton; * In the farther future, the binder logic and consequently this stage should be broken into * smaller stages. */ -@Singleton +@SysUISingleton public class RowContentBindStage extends BindStage<RowContentBindParams> { private final NotificationRowContentBinder mBinder; private final NotifInflationErrorManager mNotifInflationErrorManager; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java index 46517711a0dc..3f5867477f16 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java @@ -18,7 +18,6 @@ package com.android.systemui.statusbar.notification.row.wrapper; import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y; -import android.app.AppOpsManager; import android.app.Notification; import android.content.Context; import android.util.ArraySet; @@ -64,10 +63,6 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper { private TextView mHeaderText; private TextView mAppNameText; private ImageView mWorkProfileImage; - private View mCameraIcon; - private View mMicIcon; - private View mOverlayIcon; - private View mAppOps; private View mAudiblyAlertedIcon; private FrameLayout mIconContainer; private View mFeedbackIcon; @@ -109,7 +104,6 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper { } }, TRANSFORMING_VIEW_TITLE); resolveHeaderViews(); - addAppOpsOnClickListener(row); addFeedbackOnClickListener(row); } @@ -121,10 +115,6 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper { mExpandButton = mView.findViewById(com.android.internal.R.id.expand_button); mWorkProfileImage = mView.findViewById(com.android.internal.R.id.profile_badge); mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header); - mCameraIcon = mView.findViewById(com.android.internal.R.id.camera); - mMicIcon = mView.findViewById(com.android.internal.R.id.mic); - mOverlayIcon = mView.findViewById(com.android.internal.R.id.overlay); - mAppOps = mView.findViewById(com.android.internal.R.id.app_ops); mAudiblyAlertedIcon = mView.findViewById(com.android.internal.R.id.alerted_icon); mFeedbackIcon = mView.findViewById(com.android.internal.R.id.feedback); if (mNotificationHeader != null) { @@ -133,38 +123,6 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper { } } - private void addAppOpsOnClickListener(ExpandableNotificationRow row) { - View.OnClickListener listener = row.getAppOpsOnClickListener(); - if (mNotificationHeader != null) { - mNotificationHeader.setAppOpsOnClickListener(listener); - } - if (mAppOps != null) { - mAppOps.setOnClickListener(listener); - } - } - - /** - * Shows or hides 'app op in use' icons based on app usage. - */ - @Override - public void showAppOpsIcons(ArraySet<Integer> appOps) { - if (appOps == null) { - return; - } - if (mOverlayIcon != null) { - mOverlayIcon.setVisibility(appOps.contains(AppOpsManager.OP_SYSTEM_ALERT_WINDOW) - ? View.VISIBLE : View.GONE); - } - if (mCameraIcon != null) { - mCameraIcon.setVisibility(appOps.contains(AppOpsManager.OP_CAMERA) - ? View.VISIBLE : View.GONE); - } - if (mMicIcon != null) { - mMicIcon.setVisibility(appOps.contains(AppOpsManager.OP_RECORD_AUDIO) - ? View.VISIBLE : View.GONE); - } - } - private void addFeedbackOnClickListener(ExpandableNotificationRow row) { View.OnClickListener listener = row.getFeedbackOnClickListener(); if (mNotificationHeader != null) { @@ -304,15 +262,6 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper { mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE, mHeaderText); } - if (mCameraIcon != null) { - mTransformationHelper.addViewTransformingToSimilar(mCameraIcon); - } - if (mMicIcon != null) { - mTransformationHelper.addViewTransformingToSimilar(mMicIcon); - } - if (mOverlayIcon != null) { - mTransformationHelper.addViewTransformingToSimilar(mOverlayIcon); - } if (mAudiblyAlertedIcon != null) { mTransformationHelper.addViewTransformingToSimilar(mAudiblyAlertedIcon); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java index 93d3f3bdbe96..33c939054be5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java @@ -22,14 +22,12 @@ import android.annotation.Nullable; import android.app.Notification; import android.content.Context; import android.content.res.ColorStateList; -import android.graphics.drawable.Drawable; import android.media.MediaMetadata; import android.media.session.MediaController; import android.media.session.MediaSession; import android.media.session.PlaybackState; import android.metrics.LogMaker; import android.os.Handler; -import android.service.notification.StatusBarNotification; import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.View; @@ -43,13 +41,9 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.widget.MediaNotificationView; import com.android.systemui.Dependency; -import com.android.systemui.qs.QSPanel; -import com.android.systemui.qs.QuickQSPanel; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.TransformableView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; -import com.android.systemui.util.Utils; import java.util.Timer; import java.util.TimerTask; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java index 605fbc0f6125..42f5e389d5a8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java @@ -97,14 +97,6 @@ public abstract class NotificationViewWrapper implements TransformableView { } /** - * Show a set of app opp icons in the layout. - * - * @param appOps which app ops to show - */ - public void showAppOpsIcons(ArraySet<Integer> appOps) { - } - - /** * Shows or hides feedback icon. */ public void showFeedbackIcon(boolean show) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ForegroundServiceSectionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ForegroundServiceSectionController.kt index 5757fe8040f0..32d41a8bfab7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ForegroundServiceSectionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ForegroundServiceSectionController.kt @@ -26,23 +26,21 @@ import android.service.notification.NotificationListenerService.REASON_GROUP_SUM import android.view.LayoutInflater import android.view.View import android.widget.LinearLayout - -import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.R +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController import com.android.systemui.statusbar.notification.NotificationEntryListener import com.android.systemui.statusbar.notification.NotificationEntryManager +import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.row.DungeonRow import com.android.systemui.util.Assert - import javax.inject.Inject -import javax.inject.Singleton /** * Controller for the bottom area of NotificationStackScrollLayout. It owns swiped-away foreground * service notifications and can reinstantiate them when requested. */ -@Singleton +@SysUISingleton class ForegroundServiceSectionController @Inject constructor( val entryManager: NotificationEntryManager, val featureController: ForegroundServiceDismissalFeatureController diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java index 93c2377ccfae..a396305a49b6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java @@ -22,7 +22,6 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.drawable.ColorDrawable; import android.service.notification.StatusBarNotification; -import android.util.ArraySet; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.NotificationHeaderView; @@ -36,7 +35,7 @@ import com.android.systemui.R; import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.NotificationHeaderUtil; import com.android.systemui.statusbar.notification.NotificationUtils; -import com.android.systemui.statusbar.notification.VisualStabilityManager; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.HybridGroupManager; import com.android.systemui.statusbar.notification.row.HybridNotificationView; @@ -1303,20 +1302,6 @@ public class NotificationChildrenContainer extends ViewGroup { } /** - * Show a set of app opp icons in the layout. - * - * @param appOps which app ops to show - */ - public void showAppOpsIcons(ArraySet<Integer> appOps) { - if (mNotificationHeaderWrapper != null) { - mNotificationHeaderWrapper.showAppOpsIcons(appOps); - } - if (mNotificationHeaderWrapperLowPriority != null) { - mNotificationHeaderWrapperLowPriority.showAppOpsIcons(appOps); - } - } - - /** * Shows or hides feedback icon. */ public void showFeedbackIcon(boolean show) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java index 2c3239a45012..fe6666943e5c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.stack; import android.util.MathUtils; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -28,12 +29,11 @@ import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import java.util.HashSet; import javax.inject.Inject; -import javax.inject.Singleton; /** * A class that manages the roundness for notification views */ -@Singleton +@SysUISingleton public class NotificationRoundnessManager implements OnHeadsUpChangedListener { private final ExpandableView[] mFirstInSectionViews; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt index 17b414379f8d..cb7dfe87f7fb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt @@ -16,15 +16,15 @@ package com.android.systemui.statusbar.notification.stack +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogLevel import com.android.systemui.log.dagger.NotificationSectionLog import javax.inject.Inject -import javax.inject.Singleton private const val TAG = "NotifSections" -@Singleton +@SysUISingleton class NotificationSectionsLogger @Inject constructor( @NotificationSectionLog private val logBuffer: LogBuffer ) { 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 d2f8a39cc8fb..d4c270f45ceb 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 @@ -125,10 +125,10 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.ShadeViewRefactor; import com.android.systemui.statusbar.notification.ShadeViewRefactor.RefactorComponent; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotifCollection; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.logging.NotificationLogger; @@ -150,7 +150,6 @@ import com.android.systemui.statusbar.phone.LockscreenGestureLogger; import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChangeListener; -import com.android.systemui.statusbar.phone.NotificationIconAreaController; import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ShadeController; @@ -179,8 +178,7 @@ import javax.inject.Named; /** * A layout which handles a dynamic amount of notifications and presents them in a scrollable stack. */ -public class NotificationStackScrollLayout extends ViewGroup implements ScrollAdapter, - ConfigurationListener, Dumpable, DynamicPrivacyController.Listener { +public class NotificationStackScrollLayout extends ViewGroup implements ScrollAdapter, Dumpable { public static final float BACKGROUND_ALPHA_DIMMED = 0.7f; private static final String TAG = "StackScroller"; @@ -500,7 +498,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd private ArrayList<BiConsumer<Float, Float>> mExpandedHeightListeners = new ArrayList<>(); private int mHeadsUpInset; private HeadsUpAppearanceController mHeadsUpAppearanceController; - private NotificationIconAreaController mIconAreaController; private final NotificationLockscreenUserManager mLockscreenUserManager; private final Rect mTmpRect = new Rect(); private final FeatureFlags mFeatureFlags; @@ -669,7 +666,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd }); } - dynamicPrivacyController.addListener(this); mDynamicPrivacyController = dynamicPrivacyController; mStatusbarStateController = statusBarStateController; initializeForegroundServiceSection(fgsFeatureController); @@ -732,36 +728,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd return 0f; } - @Override - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - public void onDensityOrFontScaleChanged() { - reinflateViews(); - } - - private void reinflateViews() { + void reinflateViews() { inflateFooterView(); inflateEmptyShadeView(); updateFooter(); mSectionsManager.reinflateViews(LayoutInflater.from(mContext)); } - @Override - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - public void onThemeChanged() { - updateFooter(); - } - - @Override - public void onOverlayChanged() { - int newRadius = mContext.getResources().getDimensionPixelSize( - Utils.getThemeAttr(mContext, android.R.attr.dialogCornerRadius)); - if (mCornerRadius != newRadius) { - mCornerRadius = newRadius; - invalidate(); - } - reinflateViews(); - } - @VisibleForTesting @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) public void updateFooter() { @@ -827,7 +800,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd super.onAttachedToWindow(); ((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class)) .addCallback(mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER); - Dependency.get(ConfigurationController.class).addCallback(this); } @Override @@ -835,7 +807,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd protected void onDetachedFromWindow() { super.onDetachedFromWindow(); Dependency.get(StatusBarStateController.class).removeCallback(mStateListener); - Dependency.get(ConfigurationController.class).removeCallback(this); } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) @@ -843,9 +814,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd return mSwipeHelper; } - @Override - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - public void onUiModeChanged() { + void updateBgColor() { mBgColor = mContext.getColor(R.color.notification_shade_background_color); updateBackgroundDimming(); mShelf.onUiModeChanged(); @@ -1078,6 +1047,15 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd R.dimen.heads_up_status_bar_padding); } + void updateCornerRadius() { + int newRadius = getResources().getDimensionPixelSize( + Utils.getThemeAttr(getContext(), android.R.attr.dialogCornerRadius)); + if (mCornerRadius != newRadius) { + mCornerRadius = newRadius; + invalidate(); + } + } + @ShadeViewRefactor(RefactorComponent.COORDINATOR) private void notifyHeightChangeListener(ExpandableView view) { notifyHeightChangeListener(view, false /* needsAnimation */); @@ -3355,8 +3333,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd @ShadeViewRefactor(RefactorComponent.COORDINATOR) void onViewAddedInternal(ExpandableView child) { - child.setOnHeightChangedListener(mOnChildHeightChangedListener); updateHideSensitiveForChild(child); + child.setOnHeightChangedListener(mOnChildHeightChangedListener); generateAddAnimation(child, false /* fromMoreCard */); updateAnimationState(child); updateChronometerForChild(child); @@ -4854,7 +4832,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd * @param lightTheme True if light theme should be used. */ @ShadeViewRefactor(RefactorComponent.DECORATOR) - private void updateDecorViews(boolean lightTheme) { + void updateDecorViews(boolean lightTheme) { if (lightTheme == mUsingLightTheme) { return; } @@ -5596,11 +5574,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - public void setIconAreaController(NotificationIconAreaController controller) { - mIconAreaController = controller; - } - - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) @VisibleForTesting void clearNotifications( @SelectedRows int selection, @@ -5790,10 +5763,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd mNotificationPanelController = notificationPanelViewController; } - public void updateIconAreaViews() { - mIconAreaController.updateNotificationIcons(); - } - /** * Set how far the wake up is when waking up from pulsing. This is a height and will adjust the * notification positions accordingly. @@ -5852,17 +5821,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd mDimmedNeedsAnimation = true; } - @Override - public void onDynamicPrivacyChanged() { - if (mIsExpanded) { - // The bottom might change because we're using the final actual height of the view - mAnimateBottomOnLayout = true; - } - // Let's update the footer once the notifications have been updated (in the next frame) - post(() -> { - updateFooter(); - updateSectionBoundaries("dynamic privacy changed"); - }); + void setAnimateBottomOnLayout(boolean animateBottomOnLayout) { + mAnimateBottomOnLayout = animateBottomOnLayout; } public void setOnPulseHeightChangedListener(Runnable listener) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 53d3b7586f7e..7c29ee2b5483 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -17,7 +17,6 @@ package com.android.systemui.statusbar.notification.stack; import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME; -import static com.android.systemui.statusbar.phone.NotificationIconAreaController.HIGH_PRIORITY; import android.graphics.PointF; import android.provider.Settings; @@ -27,10 +26,12 @@ import android.view.ViewGroup; import android.view.WindowInsets; import android.widget.FrameLayout; +import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper; import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; +import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationActivityStarter; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.logging.NotificationLogger; @@ -42,11 +43,12 @@ import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.HeadsUpTouchHelper; import com.android.systemui.statusbar.phone.NotificationGroupManager; -import com.android.systemui.statusbar.phone.NotificationIconAreaController; import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; import com.android.systemui.tuner.TunerService; import java.util.function.BiConsumer; @@ -64,22 +66,78 @@ public class NotificationStackScrollLayoutController { private final HeadsUpManagerPhone mHeadsUpManager; private final NotificationRoundnessManager mNotificationRoundnessManager; private final TunerService mTunerService; + private final DynamicPrivacyController mDynamicPrivacyController; + private final ConfigurationController mConfigurationController; private final NotificationListContainerImpl mNotificationListContainer = new NotificationListContainerImpl(); private NotificationStackScrollLayout mView; + @VisibleForTesting + final View.OnAttachStateChangeListener mOnAttachStateChangeListener = + new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View v) { + mConfigurationController.addCallback(mConfigurationListener); + } + + @Override + public void onViewDetachedFromWindow(View v) { + mConfigurationController.removeCallback(mConfigurationListener); + } + }; + + private final DynamicPrivacyController.Listener mDynamicPrivacyControllerListener = () -> { + if (mView.isExpanded()) { + // The bottom might change because we're using the final actual height of the view + mView.setAnimateBottomOnLayout(true); + } + // Let's update the footer once the notifications have been updated (in the next frame) + mView.post(() -> { + updateFooter(); + updateSectionBoundaries("dynamic privacy changed"); + }); + }; + + @VisibleForTesting + final ConfigurationListener mConfigurationListener = new ConfigurationListener() { + @Override + public void onDensityOrFontScaleChanged() { + mView.reinflateViews(); + } + + @Override + public void onOverlayChanged() { + mView.updateCornerRadius(); + mView.reinflateViews(); + } + + @Override + public void onUiModeChanged() { + mView.updateBgColor(); + } + + @Override + public void onThemeChanged() { + updateFooter(); + } + }; + @Inject public NotificationStackScrollLayoutController( @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress, NotificationGutsManager notificationGutsManager, HeadsUpManagerPhone headsUpManager, NotificationRoundnessManager notificationRoundnessManager, - TunerService tunerService) { + TunerService tunerService, + DynamicPrivacyController dynamicPrivacyController, + ConfigurationController configurationController) { mAllowLongPress = allowLongPress; mNotificationGutsManager = notificationGutsManager; mHeadsUpManager = headsUpManager; mNotificationRoundnessManager = notificationRoundnessManager; mTunerService = tunerService; + mDynamicPrivacyController = dynamicPrivacyController; + mConfigurationController = configurationController; } public void attach(NotificationStackScrollLayout view) { @@ -91,15 +149,26 @@ public class NotificationStackScrollLayoutController { } mHeadsUpManager.addListener(mNotificationRoundnessManager); // TODO: why is this here? + mDynamicPrivacyController.addListener(mDynamicPrivacyControllerListener); mNotificationRoundnessManager.setOnRoundingChangedCallback(mView::invalidate); mView.addOnExpandedHeightChangedListener(mNotificationRoundnessManager::setExpanded); - mTunerService.addTunable((key, newValue) -> { - if (key.equals(Settings.Secure.NOTIFICATION_DISMISS_RTL)) { - mView.updateDismissRtlSetting("1".equals(newValue)); - } - }, HIGH_PRIORITY, Settings.Secure.NOTIFICATION_DISMISS_RTL); + mTunerService.addTunable( + (key, newValue) -> { + if (key.equals(Settings.Secure.NOTIFICATION_DISMISS_RTL)) { + mView.updateDismissRtlSetting("1".equals(newValue)); + } else if (key.equals(Settings.Secure.NOTIFICATION_HISTORY_ENABLED)) { + updateFooter(); + } + }, + Settings.Secure.NOTIFICATION_DISMISS_RTL, + Settings.Secure.NOTIFICATION_HISTORY_ENABLED); + + if (mView.isAttachedToWindow()) { + mOnAttachStateChangeListener.onViewAttachedToWindow(mView); + } + mView.addOnAttachStateChangeListener(mOnAttachStateChangeListener); } public void addOnExpandedHeightChangedListener(BiConsumer<Float, Float> listener) { @@ -479,10 +548,6 @@ public class NotificationStackScrollLayoutController { mView.updateFooter(); } - public void updateIconAreaViews() { - mView.updateIconAreaViews(); - } - public void onUpdateRowStates() { mView.onUpdateRowStates(); } @@ -504,10 +569,6 @@ public class NotificationStackScrollLayoutController { mView.setNotificationPanelController(notificationPanelViewController); } - public void setIconAreaController(NotificationIconAreaController controller) { - mView.setIconAreaController(controller); - } - public void setStatusBar(StatusBar statusBar) { mView.setStatusBar(statusBar); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java index 0e76c904f8cd..e99637867220 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -40,6 +40,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.keyguard.KeyguardViewController; import com.android.systemui.Dependency; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardViewMediator; @@ -47,6 +48,7 @@ import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationMediaManager; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.policy.KeyguardStateController; import java.io.FileDescriptor; @@ -57,12 +59,11 @@ import java.util.Map; import java.util.Optional; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controller which coordinates all the biometric unlocking actions with the UI. */ -@Singleton +@SysUISingleton public class BiometricUnlockController extends KeyguardUpdateMonitorCallback implements Dumpable { private static final String TAG = "BiometricUnlockCtrl"; @@ -157,11 +158,11 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp private DozeScrimController mDozeScrimController; private KeyguardViewMediator mKeyguardViewMediator; private ScrimController mScrimController; - private StatusBar mStatusBar; private PendingAuthenticated mPendingAuthenticated = null; private boolean mPendingShowBouncer; private boolean mHasScreenTurnedOnSinceAuthenticating; private boolean mFadedAwayAfterWakeAndUnlock; + private BiometricModeListener mBiometricModeListener; private final MetricsLogger mMetricsLogger; @@ -243,7 +244,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp @Inject public BiometricUnlockController(Context context, DozeScrimController dozeScrimController, KeyguardViewMediator keyguardViewMediator, ScrimController scrimController, - StatusBar statusBar, ShadeController shadeController, + ShadeController shadeController, NotificationShadeWindowController notificationShadeWindowController, KeyguardStateController keyguardStateController, Handler handler, KeyguardUpdateMonitor keyguardUpdateMonitor, @@ -264,7 +265,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mDozeScrimController = dozeScrimController; mKeyguardViewMediator = keyguardViewMediator; mScrimController = scrimController; - mStatusBar = statusBar; mKeyguardStateController = keyguardStateController; mHandler = handler; mWakeUpDelay = resources.getInteger(com.android.internal.R.integer.config_wakeUpDelayDoze); @@ -278,6 +278,11 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mKeyguardViewController = keyguardViewController; } + /** Sets a {@link BiometricModeListener}. */ + public void setBiometricModeListener(BiometricModeListener biometricModeListener) { + mBiometricModeListener = biometricModeListener; + } + private final Runnable mReleaseBiometricWakeLockRunnable = new Runnable() { @Override public void run() { @@ -434,19 +439,25 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp } else { mKeyguardViewMediator.onWakeAndUnlocking(); } - if (mStatusBar.getNavigationBarView() != null) { - mStatusBar.getNavigationBarView().setWakeAndUnlocking(true); - } Trace.endSection(); break; case MODE_ONLY_WAKE: case MODE_NONE: break; } - mStatusBar.notifyBiometricAuthModeChanged(); + onModeChanged(mMode); + if (mBiometricModeListener != null) { + mBiometricModeListener.notifyBiometricAuthModeChanged(); + } Trace.endSection(); } + private void onModeChanged(@WakeAndUnlockMode int mode) { + if (mBiometricModeListener != null) { + mBiometricModeListener.onModeChanged(mode); + } + } + private void showBouncer() { if (mMode == MODE_SHOW_BOUNCER) { mKeyguardViewController.showBouncer(false); @@ -619,10 +630,10 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mMode = MODE_NONE; mBiometricType = null; mNotificationShadeWindowController.setForceDozeBrightness(false); - if (mStatusBar.getNavigationBarView() != null) { - mStatusBar.getNavigationBarView().setWakeAndUnlocking(false); + if (mBiometricModeListener != null) { + mBiometricModeListener.onResetMode(); + mBiometricModeListener.notifyBiometricAuthModeChanged(); } - mStatusBar.notifyBiometricAuthModeChanged(); } @VisibleForTesting @@ -702,4 +713,14 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp return 3; } } + + /** An interface to interact with the {@link BiometricUnlockController}. */ + public interface BiometricModeListener { + /** Called when {@code mMode} is reset to {@link #MODE_NONE}. */ + void onResetMode(); + /** Called when {@code mMode} has changed in {@link #startWakeAndUnlock(int)}. */ + void onModeChanged(@WakeAndUnlockMode int mode); + /** Called after processing {@link #onModeChanged(int)}. */ + void notifyBiometricAuthModeChanged(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java index ef0f7cddba24..f25359e5f481 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java @@ -14,7 +14,6 @@ package com.android.systemui.statusbar.phone; -import static com.android.systemui.plugins.DarkIconDispatcher.DEFAULT_ICON_TINT; import static com.android.systemui.plugins.DarkIconDispatcher.getTint; import android.animation.ArgbEvaluator; @@ -25,18 +24,17 @@ import android.util.ArrayMap; import android.widget.ImageView; import com.android.systemui.R; -import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.CommandQueue; import java.io.FileDescriptor; import java.io.PrintWriter; import javax.inject.Inject; -import javax.inject.Singleton; /** */ -@Singleton +@SysUISingleton public class DarkIconDispatcherImpl implements SysuiDarkIconDispatcher, LightBarTransitionsController.DarkIntensityApplier { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java index 0731a568ae7d..31965d4fc4cd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java @@ -27,8 +27,8 @@ import android.view.ViewGroup; import android.widget.LinearLayout; import com.android.internal.statusbar.StatusBarIcon; -import com.android.systemui.DemoMode; import com.android.systemui.R; +import com.android.systemui.demomode.DemoMode; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.statusbar.StatusBarIconView; @@ -39,7 +39,9 @@ import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconStat import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState; import java.util.ArrayList; +import java.util.List; +//TODO: This should be a controller, not its own view public class DemoStatusIcons extends StatusIconContainer implements DemoMode, DarkReceiver { private static final String TAG = "DemoStatusIcons"; @@ -90,73 +92,84 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da } @Override + public List<String> demoCommands() { + List<String> commands = new ArrayList<>(); + commands.add(COMMAND_STATUS); + return commands; + } + + @Override + public void onDemoModeStarted() { + mDemoMode = true; + mStatusIcons.setVisibility(View.GONE); + setVisibility(View.VISIBLE); + } + + @Override + public void onDemoModeFinished() { + mDemoMode = false; + mStatusIcons.setVisibility(View.VISIBLE); + setVisibility(View.GONE); + } + + @Override public void dispatchDemoCommand(String command, Bundle args) { - if (!mDemoMode && command.equals(COMMAND_ENTER)) { - mDemoMode = true; - mStatusIcons.setVisibility(View.GONE); - setVisibility(View.VISIBLE); - } else if (mDemoMode && command.equals(COMMAND_EXIT)) { - mDemoMode = false; - mStatusIcons.setVisibility(View.VISIBLE); - setVisibility(View.GONE); - } else if (mDemoMode && command.equals(COMMAND_STATUS)) { - String volume = args.getString("volume"); - if (volume != null) { - int iconId = volume.equals("vibrate") ? R.drawable.stat_sys_ringer_vibrate - : 0; - updateSlot("volume", null, iconId); - } - String zen = args.getString("zen"); - if (zen != null) { - int iconId = zen.equals("dnd") ? R.drawable.stat_sys_dnd : 0; - updateSlot("zen", null, iconId); - } - String bt = args.getString("bluetooth"); - if (bt != null) { - int iconId = bt.equals("connected") - ? R.drawable.stat_sys_data_bluetooth_connected : 0; - updateSlot("bluetooth", null, iconId); - } - String location = args.getString("location"); - if (location != null) { - int iconId = location.equals("show") ? PhoneStatusBarPolicy.LOCATION_STATUS_ICON_ID - : 0; - updateSlot("location", null, iconId); - } - String alarm = args.getString("alarm"); - if (alarm != null) { - int iconId = alarm.equals("show") ? R.drawable.stat_sys_alarm - : 0; - updateSlot("alarm_clock", null, iconId); - } - String tty = args.getString("tty"); - if (tty != null) { - int iconId = tty.equals("show") ? R.drawable.stat_sys_tty_mode - : 0; - updateSlot("tty", null, iconId); - } - String mute = args.getString("mute"); - if (mute != null) { - int iconId = mute.equals("show") ? android.R.drawable.stat_notify_call_mute - : 0; - updateSlot("mute", null, iconId); - } - String speakerphone = args.getString("speakerphone"); - if (speakerphone != null) { - int iconId = speakerphone.equals("show") ? android.R.drawable.stat_sys_speakerphone - : 0; - updateSlot("speakerphone", null, iconId); - } - String cast = args.getString("cast"); - if (cast != null) { - int iconId = cast.equals("show") ? R.drawable.stat_sys_cast : 0; - updateSlot("cast", null, iconId); - } - String hotspot = args.getString("hotspot"); - if (hotspot != null) { - int iconId = hotspot.equals("show") ? R.drawable.stat_sys_hotspot : 0; - updateSlot("hotspot", null, iconId); - } + String volume = args.getString("volume"); + if (volume != null) { + int iconId = volume.equals("vibrate") ? R.drawable.stat_sys_ringer_vibrate + : 0; + updateSlot("volume", null, iconId); + } + String zen = args.getString("zen"); + if (zen != null) { + int iconId = zen.equals("dnd") ? R.drawable.stat_sys_dnd : 0; + updateSlot("zen", null, iconId); + } + String bt = args.getString("bluetooth"); + if (bt != null) { + int iconId = bt.equals("connected") + ? R.drawable.stat_sys_data_bluetooth_connected : 0; + updateSlot("bluetooth", null, iconId); + } + String location = args.getString("location"); + if (location != null) { + int iconId = location.equals("show") ? PhoneStatusBarPolicy.LOCATION_STATUS_ICON_ID + : 0; + updateSlot("location", null, iconId); + } + String alarm = args.getString("alarm"); + if (alarm != null) { + int iconId = alarm.equals("show") ? R.drawable.stat_sys_alarm + : 0; + updateSlot("alarm_clock", null, iconId); + } + String tty = args.getString("tty"); + if (tty != null) { + int iconId = tty.equals("show") ? R.drawable.stat_sys_tty_mode + : 0; + updateSlot("tty", null, iconId); + } + String mute = args.getString("mute"); + if (mute != null) { + int iconId = mute.equals("show") ? android.R.drawable.stat_notify_call_mute + : 0; + updateSlot("mute", null, iconId); + } + String speakerphone = args.getString("speakerphone"); + if (speakerphone != null) { + int iconId = speakerphone.equals("show") ? android.R.drawable.stat_sys_speakerphone + : 0; + updateSlot("speakerphone", null, iconId); + } + String cast = args.getString("cast"); + if (cast != null) { + int iconId = cast.equals("show") ? R.drawable.stat_sys_cast : 0; + updateSlot("cast", null, iconId); + } + String hotspot = args.getString("hotspot"); + if (hotspot != null) { + int iconId = hotspot.equals("show") ? R.drawable.stat_sys_hotspot : 0; + updateSlot("hotspot", null, iconId); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java index 5fab4bea9a04..64951448a543 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java @@ -25,6 +25,7 @@ import android.provider.Settings; import android.util.MathUtils; import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.doze.AlwaysOnDisplayPolicy; import com.android.systemui.doze.DozeScreenState; @@ -34,12 +35,11 @@ import com.android.systemui.tuner.TunerService; import java.io.PrintWriter; import javax.inject.Inject; -import javax.inject.Singleton; /** * Retrieve doze information */ -@Singleton +@SysUISingleton public class DozeParameters implements TunerService.Tunable, com.android.systemui.plugins.statusbar.DozeParameters { private static final int MAX_DURATION = 60 * 1000; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java index e7d6eba1dcb3..b2cf72aca864 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java @@ -22,18 +22,18 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Dependency; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controller which handles all the doze animations of the scrims. */ -@Singleton +@SysUISingleton public class DozeScrimController implements StateListener { private static final String TAG = "DozeScrimController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java index 4afeba8de211..efb24693beff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java @@ -31,16 +31,18 @@ import android.view.View; import com.android.internal.annotations.VisibleForTesting; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.assist.AssistManager; +import com.android.systemui.biometrics.AuthController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; import com.android.systemui.doze.DozeReceiver; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; @@ -48,14 +50,13 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController; import java.util.ArrayList; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; /** * Implementation of DozeHost for SystemUI. */ -@Singleton +@SysUISingleton public final class DozeServiceHost implements DozeHost { private static final String TAG = "DozeServiceHost"; private final ArrayList<Callback> mCallbacks = new ArrayList<>(); @@ -81,12 +82,12 @@ public final class DozeServiceHost implements DozeHost { private final Lazy<AssistManager> mAssistManagerLazy; private final DozeScrimController mDozeScrimController; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; - private final VisualStabilityManager mVisualStabilityManager; private final PulseExpansionHandler mPulseExpansionHandler; private final NotificationShadeWindowController mNotificationShadeWindowController; private final NotificationWakeUpCoordinator mNotificationWakeUpCoordinator; private NotificationShadeWindowViewController mNotificationShadeWindowViewController; private final LockscreenLockIconController mLockscreenLockIconController; + private final AuthController mAuthController; private NotificationIconAreaController mNotificationIconAreaController; private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private NotificationPanelViewController mNotificationPanel; @@ -105,11 +106,12 @@ public final class DozeServiceHost implements DozeHost { KeyguardViewMediator keyguardViewMediator, Lazy<AssistManager> assistManagerLazy, DozeScrimController dozeScrimController, KeyguardUpdateMonitor keyguardUpdateMonitor, - VisualStabilityManager visualStabilityManager, PulseExpansionHandler pulseExpansionHandler, NotificationShadeWindowController notificationShadeWindowController, NotificationWakeUpCoordinator notificationWakeUpCoordinator, - LockscreenLockIconController lockscreenLockIconController) { + LockscreenLockIconController lockscreenLockIconController, + AuthController authController, + NotificationIconAreaController notificationIconAreaController) { super(); mDozeLog = dozeLog; mPowerManager = powerManager; @@ -124,11 +126,12 @@ public final class DozeServiceHost implements DozeHost { mAssistManagerLazy = assistManagerLazy; mDozeScrimController = dozeScrimController; mKeyguardUpdateMonitor = keyguardUpdateMonitor; - mVisualStabilityManager = visualStabilityManager; mPulseExpansionHandler = pulseExpansionHandler; mNotificationShadeWindowController = notificationShadeWindowController; mNotificationWakeUpCoordinator = notificationWakeUpCoordinator; mLockscreenLockIconController = lockscreenLockIconController; + mAuthController = authController; + mNotificationIconAreaController = notificationIconAreaController; } // TODO: we should try to not pass status bar in here if we can avoid it. @@ -136,13 +139,13 @@ public final class DozeServiceHost implements DozeHost { /** * Initialize instance with objects only available later during execution. */ - public void initialize(StatusBar statusBar, - NotificationIconAreaController notificationIconAreaController, + public void initialize( + StatusBar statusBar, StatusBarKeyguardViewManager statusBarKeyguardViewManager, NotificationShadeWindowViewController notificationShadeWindowViewController, - NotificationPanelViewController notificationPanel, View ambientIndicationContainer) { + NotificationPanelViewController notificationPanel, + View ambientIndicationContainer) { mStatusBar = statusBar; - mNotificationIconAreaController = notificationIconAreaController; mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mNotificationPanel = notificationPanel; mNotificationShadeWindowViewController = notificationShadeWindowViewController; @@ -254,11 +257,10 @@ public final class DozeServiceHost implements DozeHost { } private void setPulsing(boolean pulsing) { - mStatusBarStateController.setPulsing(pulsing); mStatusBarKeyguardViewManager.setPulsing(pulsing); mKeyguardViewMediator.setPulsing(pulsing); mNotificationPanel.setPulsing(pulsing); - mVisualStabilityManager.setPulsing(pulsing); + mStatusBarStateController.setPulsing(pulsing); mIgnoreTouchWhilePulsing = false; if (mKeyguardUpdateMonitor != null && passiveAuthInterrupt) { mKeyguardUpdateMonitor.onAuthInterruptDetected(pulsing /* active */); @@ -296,6 +298,7 @@ public final class DozeServiceHost implements DozeHost { @Override public void dozeTimeTick() { mNotificationPanel.dozeTimeTick(); + mAuthController.dozeTimeTick(); if (mAmbientIndicationContainer instanceof DozeReceiver) { ((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java index 1d82e0808332..8092cb910b07 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java @@ -31,8 +31,8 @@ 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.StatusBarState; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.HeadsUpManager; @@ -58,6 +58,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, private final NotificationGroupManager mGroupManager; private final List<OnHeadsUpPhoneListenerChange> mHeadsUpPhoneListeners = new ArrayList<>(); private final int mAutoHeadsUpNotificationDecay; + // TODO (b/162832756): remove visual stability manager when migrating to new pipeline private VisualStabilityManager mVisualStabilityManager; private boolean mReleaseOnExpandFinish; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt index 0827511cac34..242bd0a29d2f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt @@ -21,6 +21,7 @@ import android.content.pm.PackageManager import android.hardware.biometrics.BiometricSourceType import android.provider.Settings import com.android.systemui.Dumpable +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.NotificationLockscreenUserManager @@ -30,9 +31,8 @@ import com.android.systemui.tuner.TunerService import java.io.FileDescriptor import java.io.PrintWriter import javax.inject.Inject -import javax.inject.Singleton -@Singleton +@SysUISingleton open class KeyguardBypassController : Dumpable { private val mKeyguardStateController: KeyguardStateController diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java index 834d2a5ae4a0..c0181f448cc1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java @@ -18,16 +18,16 @@ package com.android.systemui.statusbar.phone; import android.util.Log; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.ActivityStarter.OnDismissAction; import javax.inject.Inject; -import javax.inject.Singleton; /** * Executes actions that require the screen to be unlocked. Delegates the actual handling to an * implementation passed via {@link #setDismissHandler}. */ -@Singleton +@SysUISingleton public class KeyguardDismissUtil implements KeyguardDismissHandler { private static final String TAG = "KeyguardDismissUtil"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java index e763496da859..817b86bf643e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java @@ -21,14 +21,14 @@ import android.service.notification.StatusBarNotification; import android.util.Log; import com.android.systemui.Dependency; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import javax.inject.Inject; -import javax.inject.Singleton; -@Singleton +@SysUISingleton public class KeyguardEnvironmentImpl implements KeyguardEnvironment { private static final String TAG = "KeyguardEnvironmentImpl"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java index 982773aa9d86..24c902151d7c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java @@ -32,6 +32,7 @@ import com.android.internal.colorextraction.ColorExtractor.GradientColors; import com.android.internal.view.AppearanceRegion; import com.android.systemui.Dumpable; import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.shared.system.QuickStepContract; @@ -41,12 +42,11 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controls how light status bar flag applies to the icons. */ -@Singleton +@SysUISingleton public class LightBarController implements BatteryController.BatteryStateChangeCallback, Dumpable { private static final float NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD = 0.1f; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java index 8e192c5bf17d..d27a3d53c0a2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java @@ -29,13 +29,13 @@ import android.view.animation.AccelerateInterpolator; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.NotificationVisibility; import com.android.internal.view.AppearanceRegion; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import javax.inject.Inject; -import javax.inject.Singleton; /** * Apps can request a low profile mode {@link View.SYSTEM_UI_FLAG_LOW_PROFILE} @@ -45,7 +45,7 @@ import javax.inject.Singleton; * This controller shows and hides the notification dot in the status bar to indicate * whether there are notifications when the device is in {@link View.SYSTEM_UI_FLAG_LOW_PROFILE}. */ -@Singleton +@SysUISingleton public class LightsOutNotifController { private final CommandQueue mCommandQueue; private final NotificationEntryManager mEntryManager; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java index 0d6597f1b11b..094ebb9ef0a7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java @@ -27,15 +27,15 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.Dependency; import com.android.systemui.EventLogConstants; import com.android.systemui.EventLogTags; +import com.android.systemui.dagger.SysUISingleton; import javax.inject.Inject; -import javax.inject.Singleton; /** * Wrapper that emits both new- and old-style gesture logs. * TODO: delete this once the old logs are no longer needed. */ -@Singleton +@SysUISingleton public class LockscreenGestureLogger { /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java index 1dc0f070835b..11ceedf79227 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java @@ -37,6 +37,7 @@ import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dock.DockManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -54,10 +55,9 @@ import com.android.systemui.statusbar.policy.KeyguardStateController; import java.util.Optional; import javax.inject.Inject; -import javax.inject.Singleton; /** Controls the {@link LockIcon} in the lockscreen. */ -@Singleton +@SysUISingleton public class LockscreenLockIconController { private final LockscreenGestureLogger mLockscreenGestureLogger; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java index 04211dff53b6..a6811c6b8ba4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java @@ -42,6 +42,7 @@ import androidx.annotation.NonNull; import com.android.internal.util.IndentingPrintWriter; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.NotificationMediaManager; @@ -53,12 +54,11 @@ import java.io.PrintWriter; import java.util.Objects; import javax.inject.Inject; -import javax.inject.Singleton; /** * Manages the lockscreen wallpaper. */ -@Singleton +@SysUISingleton public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implements Runnable, Dumpable { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java index 07e9f944b802..94d1bf4be806 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java @@ -24,18 +24,20 @@ import android.content.pm.UserInfo; import android.os.UserHandle; import android.os.UserManager; +import androidx.annotation.NonNull; + import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** */ -@Singleton +@SysUISingleton public class ManagedProfileControllerImpl implements ManagedProfileController { private final List<Callback> mCallbacks = new ArrayList<>(); @@ -57,7 +59,8 @@ public class ManagedProfileControllerImpl implements ManagedProfileController { mProfiles = new LinkedList<UserInfo>(); } - public void addCallback(Callback callback) { + @Override + public void addCallback(@NonNull Callback callback) { mCallbacks.add(callback); if (mCallbacks.size() == 1) { setListening(true); @@ -65,7 +68,8 @@ public class ManagedProfileControllerImpl implements ManagedProfileController { callback.onManagedProfileChanged(); } - public void removeCallback(Callback callback) { + @Override + public void removeCallback(@NonNull Callback callback) { if (mCallbacks.remove(callback) && mCallbacks.size() == 0) { setListening(false); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java index 80785db6df3e..c44c59c02810 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java @@ -23,6 +23,7 @@ import android.util.Log; import com.android.systemui.Dependency; import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import com.android.systemui.statusbar.StatusBarState; @@ -40,14 +41,13 @@ import java.util.Map; import java.util.Objects; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; /** * A class to handle notifications and their corresponding groups. */ -@Singleton +@SysUISingleton public class NotificationGroupManager implements OnHeadsUpChangedListener, StateListener { private static final String TAG = "NotificationGroupManager"; 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 7bbe1c986249..bda35fb0a48e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java @@ -5,9 +5,9 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.Color; import android.graphics.Rect; +import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; import android.widget.FrameLayout; import androidx.annotation.NonNull; @@ -20,6 +20,9 @@ import com.android.settingslib.Utils; import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.demomode.DemoMode; +import com.android.systemui.demomode.DemoModeController; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -31,20 +34,26 @@ import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; +import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.function.Function; +import javax.inject.Inject; + /** * A controller for the space in the status bar to the left of the system icons. This area is * normally reserved for notifications. */ -public class NotificationIconAreaController implements DarkReceiver, +@SysUISingleton +public class NotificationIconAreaController implements + DarkReceiver, StatusBarStateController.StateListener, - NotificationWakeUpCoordinator.WakeUpListener { + NotificationWakeUpCoordinator.WakeUpListener, + DemoMode { public static final String HIGH_PRIORITY = "high_priority"; private static final long AOD_ICONS_APPEAR_DURATION = 200; @@ -57,13 +66,14 @@ public class NotificationIconAreaController implements DarkReceiver, private final KeyguardBypassController mBypassController; private final DozeParameters mDozeParameters; private final BubbleController mBubbleController; + private final StatusBarWindowController mStatusBarWindowController; private int mIconSize; private int mIconHPadding; private int mIconTint = Color.WHITE; private int mCenteredIconTint = Color.WHITE; - private StatusBar mStatusBar; + private List<ListEntry> mNotificationEntries = List.of(); protected View mNotificationIconArea; private NotificationIconContainer mNotificationIcons; private NotificationIconContainer mShelfIcons; @@ -72,8 +82,10 @@ public class NotificationIconAreaController implements DarkReceiver, private NotificationIconContainer mAodIcons; private StatusBarIconView mCenteredIconView; private final Rect mTintArea = new Rect(); - private ViewGroup mNotificationScrollLayout; private Context mContext; + + private final DemoModeController mDemoModeController; + private int mAodIconAppearTranslation; private boolean mAnimationsEnabled; @@ -88,24 +100,24 @@ public class NotificationIconAreaController implements DarkReceiver, new NotificationListener.NotificationSettingsListener() { @Override public void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) { - mShowLowPriority = !hideSilentStatusIcons; - if (mNotificationScrollLayout != null) { - updateStatusBarIcons(); - } + mShowLowPriority = !hideSilentStatusIcons; + updateStatusBarIcons(); } }; + @Inject public NotificationIconAreaController( Context context, - StatusBar statusBar, StatusBarStateController statusBarStateController, NotificationWakeUpCoordinator wakeUpCoordinator, KeyguardBypassController keyguardBypassController, NotificationMediaManager notificationMediaManager, NotificationListener notificationListener, DozeParameters dozeParameters, - BubbleController bubbleController) { - mStatusBar = statusBar; + BubbleController bubbleController, + DemoModeController demoModeController, + DarkIconDispatcher darkIconDispatcher, + StatusBarWindowController statusBarWindowController) { mContrastColorUtil = ContrastColorUtil.getInstance(context); mContext = context; mStatusBarStateController = statusBarStateController; @@ -116,10 +128,14 @@ public class NotificationIconAreaController implements DarkReceiver, wakeUpCoordinator.addListener(this); mBypassController = keyguardBypassController; mBubbleController = bubbleController; + mDemoModeController = demoModeController; + mDemoModeController.addCallback(this); + mStatusBarWindowController = statusBarWindowController; notificationListener.addNotificationSettingsListener(mSettingsListener); initializeNotificationAreaViews(context); reloadAodColor(); + darkIconDispatcher.addDarkReceiver(this); } protected View inflateIconArea(LayoutInflater inflater) { @@ -136,22 +152,21 @@ public class NotificationIconAreaController implements DarkReceiver, mNotificationIconArea = inflateIconArea(layoutInflater); mNotificationIcons = mNotificationIconArea.findViewById(R.id.notificationIcons); - mNotificationScrollLayout = mStatusBar.getNotificationScrollLayout(); - mCenteredIconArea = layoutInflater.inflate(R.layout.center_icon_area, null); mCenteredIcon = mCenteredIconArea.findViewById(R.id.centeredIcon); - - initAodIcons(); } - public void initAodIcons() { + /** + * Called by the StatusBar. The StatusBar passes the NotificationIconContainer which holds + * the aod icons. + */ + void setupAodIcons(@NonNull NotificationIconContainer aodIcons) { boolean changed = mAodIcons != null; if (changed) { mAodIcons.setAnimationsEnabled(false); mAodIcons.removeAllViews(); } - mAodIcons = mStatusBar.getNotificationShadeWindowView().findViewById( - R.id.clock_notification_icon_container); + mAodIcons = aodIcons; mAodIcons.setOnLockScreen(true); updateAodIconsVisibility(false /* animate */); updateAnimations(); @@ -189,7 +204,7 @@ public class NotificationIconAreaController implements DarkReceiver, @NonNull private FrameLayout.LayoutParams generateIconLayoutParams() { return new FrameLayout.LayoutParams( - mIconSize + 2 * mIconHPadding, getHeight()); + mIconSize + 2 * mIconHPadding, mStatusBarWindowController.getStatusBarHeight()); } private void reloadDimens(Context context) { @@ -228,29 +243,17 @@ public class NotificationIconAreaController implements DarkReceiver, mTintArea.set(tintArea); } - if (mNotificationIconArea != null) { - if (DarkIconDispatcher.isInArea(tintArea, mNotificationIconArea)) { - mIconTint = iconTint; - } - } else { + if (DarkIconDispatcher.isInArea(tintArea, mNotificationIconArea)) { mIconTint = iconTint; } - if (mCenteredIconArea != null) { - if (DarkIconDispatcher.isInArea(tintArea, mCenteredIconArea)) { - mCenteredIconTint = iconTint; - } - } else { + if (DarkIconDispatcher.isInArea(tintArea, mCenteredIconArea)) { mCenteredIconTint = iconTint; } applyNotificationIconsTint(); } - protected int getHeight() { - return mStatusBar.getStatusBarHeight(); - } - protected boolean shouldShowNotificationIcon(NotificationEntry entry, boolean showAmbient, boolean showLowPriority, boolean hideDismissed, boolean hideRepliedMessages, boolean hideCurrentMedia, boolean hideCenteredIcon, @@ -300,11 +303,15 @@ public class NotificationIconAreaController implements DarkReceiver, } return true; } - /** * Updates the notifications with the given list of notifications to display. */ - public void updateNotificationIcons() { + public void updateNotificationIcons(List<ListEntry> entries) { + mNotificationEntries = entries; + updateNotificationIcons(); + } + + private void updateNotificationIcons() { updateStatusBarIcons(); updateShelfIcons(); updateCenterIcon(); @@ -381,18 +388,15 @@ public class NotificationIconAreaController implements DarkReceiver, NotificationIconContainer hostLayout, boolean showAmbient, boolean showLowPriority, boolean hideDismissed, boolean hideRepliedMessages, boolean hideCurrentMedia, boolean hideCenteredIcon, boolean hidePulsing, boolean onlyShowCenteredIcon) { - ArrayList<StatusBarIconView> toShow = new ArrayList<>( - mNotificationScrollLayout.getChildCount()); - + ArrayList<StatusBarIconView> toShow = new ArrayList<>(mNotificationEntries.size()); // Filter out ambient notifications and notification children. - for (int i = 0; i < mNotificationScrollLayout.getChildCount(); i++) { - View view = mNotificationScrollLayout.getChildAt(i); - if (view instanceof ExpandableNotificationRow) { - NotificationEntry ent = ((ExpandableNotificationRow) view).getEntry(); - if (shouldShowNotificationIcon(ent, showAmbient, showLowPriority, hideDismissed, + for (int i = 0; i < mNotificationEntries.size(); i++) { + NotificationEntry entry = mNotificationEntries.get(i).getRepresentativeEntry(); + if (entry != null && entry.getRow() != null) { + if (shouldShowNotificationIcon(entry, showAmbient, showLowPriority, hideDismissed, hideRepliedMessages, hideCurrentMedia, hideCenteredIcon, hidePulsing, onlyShowCenteredIcon)) { - StatusBarIconView iconView = function.apply(ent); + StatusBarIconView iconView = function.apply(entry); if (iconView != null) { toShow.add(iconView); } @@ -597,13 +601,16 @@ public class NotificationIconAreaController implements DarkReceiver, mAodIconTint = Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColor); } + private void updateAodIconColors() { - for (int i = 0; i < mAodIcons.getChildCount(); i++) { - final StatusBarIconView iv = (StatusBarIconView) mAodIcons.getChildAt(i); - if (iv.getWidth() != 0) { - updateTintForIcon(iv, mAodIconTint); - } else { - iv.executeOnLayout(() -> updateTintForIcon(iv, mAodIconTint)); + if (mAodIcons != null) { + for (int i = 0; i < mAodIcons.getChildCount(); i++) { + final StatusBarIconView iv = (StatusBarIconView) mAodIcons.getChildAt(i); + if (iv.getWidth() != 0) { + updateTintForIcon(iv, mAodIconTint); + } else { + iv.executeOnLayout(() -> updateTintForIcon(iv, mAodIconTint)); + } } } } @@ -666,4 +673,27 @@ public class NotificationIconAreaController implements DarkReceiver, } } } + + @Override + public List<String> demoCommands() { + ArrayList<String> commands = new ArrayList<>(); + commands.add(DemoMode.COMMAND_NOTIFICATIONS); + return commands; + } + + @Override + public void dispatchDemoCommand(String command, Bundle args) { + if (mNotificationIconArea != null) { + String visible = args.getString("visible"); + int vis = "false".equals(visible) ? View.INVISIBLE : View.VISIBLE; + mNotificationIconArea.setVisibility(vis); + } + } + + @Override + public void onDemoModeFinished() { + if (mNotificationIconArea != null) { + mNotificationIconArea.setVisibility(View.VISIBLE); + } + } } 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 42fbe5967d42..5974a53fc86d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -100,6 +100,7 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; import com.android.systemui.statusbar.notification.PropertyAnimator; import com.android.systemui.statusbar.notification.ViewGroupFadeHelper; +import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -177,6 +178,7 @@ public class NotificationPanelViewController extends PanelViewController { private final ConfigurationController mConfigurationController; private final FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder; private final NotificationStackScrollLayoutController mNotificationStackScrollLayoutController; + private final NotificationIconAreaController mNotificationIconAreaController; // Cap and total height of Roboto font. Needs to be adjusted when font for the big clock is // changed. @@ -502,7 +504,8 @@ public class NotificationPanelViewController extends PanelViewController { BiometricUnlockController biometricUnlockController, StatusBarKeyguardViewManager statusBarKeyguardViewManager, Provider<KeyguardClockSwitchController> keyguardClockSwitchControllerProvider, - NotificationStackScrollLayoutController notificationStackScrollLayoutController) { + NotificationStackScrollLayoutController notificationStackScrollLayoutController, + NotificationIconAreaController notificationIconAreaController) { super(view, falsingManager, dozeLog, keyguardStateController, (SysuiStatusBarStateController) statusBarStateController, vibratorHelper, latencyTracker, flingAnimationUtilsBuilder, statusBarTouchableRegionManager); @@ -516,6 +519,7 @@ public class NotificationPanelViewController extends PanelViewController { mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mKeyguardClockSwitchControllerProvider = keyguardClockSwitchControllerProvider; mNotificationStackScrollLayoutController = notificationStackScrollLayoutController; + mNotificationIconAreaController = notificationIconAreaController; mView.setWillNotDraw(!DEBUG); mInjectionInflationController = injectionInflationController; mFalsingManager = falsingManager; @@ -3066,7 +3070,19 @@ public class NotificationPanelViewController extends PanelViewController { mNotificationStackScrollLayoutController.updateSpeedBumpIndex(); mNotificationStackScrollLayoutController.updateFooter(); updateShowEmptyShadeView(); - mNotificationStackScrollLayoutController.updateIconAreaViews(); + mNotificationIconAreaController.updateNotificationIcons(createVisibleEntriesList()); + } + + private List<ListEntry> createVisibleEntriesList() { + List<ListEntry> entries = new ArrayList<>( + mNotificationStackScrollLayoutController.getChildCount()); + for (int i = 0; i < mNotificationStackScrollLayoutController.getChildCount(); i++) { + View view = mNotificationStackScrollLayoutController.getChildAt(i); + if (view instanceof ExpandableNotificationRow) { + entries.add(((ExpandableNotificationRow) view).getEntry()); + } + } + return entries; } public void onUpdateRowStates() { @@ -3094,15 +3110,17 @@ public class NotificationPanelViewController extends PanelViewController { mNotificationStackScrollLayoutController.setScrollingEnabled(b); } - public void initDependencies(StatusBar statusBar, NotificationGroupManager groupManager, + /** + * Initialize objects instead of injecting to avoid circular dependencies. + */ + public void initDependencies( + StatusBar statusBar, + NotificationGroupManager groupManager, NotificationShelfController notificationShelfController, - NotificationIconAreaController notificationIconAreaController, ScrimController scrimController) { setStatusBar(statusBar); setGroupManager(mGroupManager); mNotificationStackScrollLayoutController.setNotificationPanelController(this); - mNotificationStackScrollLayoutController - .setIconAreaController(notificationIconAreaController); mNotificationStackScrollLayoutController.setStatusBar(statusBar); mNotificationStackScrollLayoutController.setGroupManager(groupManager); mNotificationStackScrollLayoutController.setShelfController(notificationShelfController); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java index bc73be19ab59..3c43a1777171 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java @@ -43,11 +43,12 @@ import android.view.WindowManager.LayoutParams; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; -import com.android.systemui.statusbar.RemoteInputController.Callback; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -66,14 +67,13 @@ import java.util.Set; import java.util.function.Consumer; import javax.inject.Inject; -import javax.inject.Singleton; /** * Encapsulates all logic for the notification shade window state management. */ -@Singleton -public class NotificationShadeWindowController implements Callback, Dumpable, - ConfigurationListener { +@SysUISingleton +public class NotificationShadeWindowControllerImpl implements NotificationShadeWindowController, + Dumpable, ConfigurationListener { private static final String TAG = "NotificationShadeWindowController"; private static final boolean DEBUG = false; @@ -103,7 +103,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, private final SysuiColorExtractor mColorExtractor; @Inject - public NotificationShadeWindowController(Context context, WindowManager windowManager, + public NotificationShadeWindowControllerImpl(Context context, WindowManager windowManager, IActivityManager activityManager, DozeParameters dozeParameters, StatusBarStateController statusBarStateController, ConfigurationController configurationController, @@ -147,6 +147,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, /** * Register to receive notifications about status bar window state changes. */ + @Override public void registerCallback(StatusBarWindowCallback callback) { // Prevent adding duplicate callbacks for (int i = 0; i < mCallbacks.size(); i++) { @@ -161,6 +162,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, * Register a listener to monitor scrims visibility * @param listener A listener to monitor scrims visibility */ + @Override public void setScrimsVisibilityListener(Consumer<Integer> listener) { if (listener != null && mScrimsVisibilityListener != listener) { mScrimsVisibilityListener = listener; @@ -176,6 +178,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, /** * Adds the notification shade view to the window manager. */ + @Override public void attach() { // Now that the notification shade encompasses the sliding panel and its // translucent backdrop, the entire thing is made TRANSLUCENT and is @@ -214,14 +217,17 @@ public class NotificationShadeWindowController implements Callback, Dumpable, } } + @Override public void setNotificationShadeView(ViewGroup view) { mNotificationShadeView = view; } + @Override public ViewGroup getNotificationShadeView() { return mNotificationShadeView; } + @Override public void setDozeScreenBrightness(int value) { mScreenBrightnessDoze = value / 255f; } @@ -406,6 +412,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, notifyStateChangedCallbacks(); } + @Override public void notifyStateChangedCallbacks() { for (int i = 0; i < mCallbacks.size(); i++) { StatusBarWindowCallback cb = mCallbacks.get(i).get(); @@ -445,62 +452,74 @@ public class NotificationShadeWindowController implements Callback, Dumpable, } } + @Override public void setKeyguardShowing(boolean showing) { mCurrentState.mKeyguardShowing = showing; apply(mCurrentState); } + @Override public void setKeyguardOccluded(boolean occluded) { mCurrentState.mKeyguardOccluded = occluded; apply(mCurrentState); } + @Override public void setKeyguardNeedsInput(boolean needsInput) { mCurrentState.mKeyguardNeedsInput = needsInput; apply(mCurrentState); } + @Override public void setPanelVisible(boolean visible) { mCurrentState.mPanelVisible = visible; mCurrentState.mNotificationShadeFocusable = visible; apply(mCurrentState); } + @Override public void setNotificationShadeFocusable(boolean focusable) { mCurrentState.mNotificationShadeFocusable = focusable; apply(mCurrentState); } + @Override public void setBouncerShowing(boolean showing) { mCurrentState.mBouncerShowing = showing; apply(mCurrentState); } + @Override public void setBackdropShowing(boolean showing) { mCurrentState.mBackdropShowing = showing; apply(mCurrentState); } + @Override public void setKeyguardFadingAway(boolean keyguardFadingAway) { mCurrentState.mKeyguardFadingAway = keyguardFadingAway; apply(mCurrentState); } + @Override public void setQsExpanded(boolean expanded) { mCurrentState.mQsExpanded = expanded; apply(mCurrentState); } + @Override public void setForceUserActivity(boolean forceUserActivity) { mCurrentState.mForceUserActivity = forceUserActivity; apply(mCurrentState); } - void setLaunchingActivity(boolean launching) { + @Override + public void setLaunchingActivity(boolean launching) { mCurrentState.mLaunchingActivity = launching; apply(mCurrentState); } + @Override public void setScrimsVisibility(int scrimsVisibility) { mCurrentState.mScrimsVisibility = scrimsVisibility; apply(mCurrentState); @@ -512,6 +531,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, * {@link com.android.systemui.statusbar.NotificationShadeDepthController}. * @param backgroundBlurRadius Radius in pixels. */ + @Override public void setBackgroundBlurRadius(int backgroundBlurRadius) { if (mCurrentState.mBackgroundBlurRadius == backgroundBlurRadius) { return; @@ -520,11 +540,13 @@ public class NotificationShadeWindowController implements Callback, Dumpable, apply(mCurrentState); } + @Override public void setHeadsUpShowing(boolean showing) { mCurrentState.mHeadsUpShowing = showing; apply(mCurrentState); } + @Override public void setWallpaperSupportsAmbientMode(boolean supportsAmbientMode) { mCurrentState.mWallpaperSupportsAmbientMode = supportsAmbientMode; apply(mCurrentState); @@ -543,11 +565,13 @@ public class NotificationShadeWindowController implements Callback, Dumpable, * Used for when a heads-up comes in but we still need to wait for the touchable regions to * be computed. */ + @Override public void setForceWindowCollapsed(boolean force) { mCurrentState.mForceCollapsed = force; apply(mCurrentState); } + @Override public void setPanelExpanded(boolean isExpanded) { mCurrentState.mPanelExpanded = isExpanded; apply(mCurrentState); @@ -563,16 +587,19 @@ public class NotificationShadeWindowController implements Callback, Dumpable, * Set whether the screen brightness is forced to the value we use for doze mode by the status * bar window. */ + @Override public void setForceDozeBrightness(boolean forceDozeBrightness) { mCurrentState.mForceDozeBrightness = forceDozeBrightness; apply(mCurrentState); } + @Override public void setDozing(boolean dozing) { mCurrentState.mDozing = dozing; apply(mCurrentState); } + @Override public void setForcePluginOpen(boolean forcePluginOpen) { mCurrentState.mForcePluginOpen = forcePluginOpen; apply(mCurrentState); @@ -584,10 +611,12 @@ public class NotificationShadeWindowController implements Callback, Dumpable, /** * The forcePluginOpen state for the status bar. */ + @Override public boolean getForcePluginOpen() { return mCurrentState.mForcePluginOpen; } + @Override public void setNotTouchable(boolean notTouchable) { mCurrentState.mNotTouchable = notTouchable; apply(mCurrentState); @@ -596,24 +625,29 @@ public class NotificationShadeWindowController implements Callback, Dumpable, /** * Whether the status bar panel is expanded or not. */ + @Override public boolean getPanelExpanded() { return mCurrentState.mPanelExpanded; } + @Override public void setStateListener(OtherwisedCollapsedListener listener) { mListener = listener; } + @Override public void setForcePluginOpenListener(ForcePluginOpenListener listener) { mForcePluginOpenListener = listener; } + @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(TAG + ":"); pw.println(" mKeyguardDisplayMode=" + mKeyguardDisplayMode); pw.println(mCurrentState); } + @Override public boolean isShowingWallpaper() { return !mCurrentState.mBackdropShowing; } @@ -632,6 +666,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, /** * When keyguard will be dismissed but didn't start animation yet. */ + @Override public void setKeyguardGoingAway(boolean goingAway) { mCurrentState.mKeyguardGoingAway = goingAway; apply(mCurrentState); @@ -642,6 +677,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, * animation is performed, the component should remove itself from the list of features that * are forcing SystemUI to be top-ui. */ + @Override public void setRequestTopUi(boolean requestTopUi, String componentTag) { if (requestTopUi) { mCurrentState.mComponentsForcingTopUi.add(componentTag); @@ -725,23 +761,4 @@ public class NotificationShadeWindowController implements Callback, Dumpable, setDozing(isDozing); } }; - - /** - * Custom listener to pipe data back to plugins about whether or not the status bar would be - * collapsed if not for the plugin. - * TODO: Find cleaner way to do this. - */ - public interface OtherwisedCollapsedListener { - void setWouldOtherwiseCollapse(boolean otherwiseCollapse); - } - - /** - * Listener to indicate forcePluginOpen has changed - */ - public interface ForcePluginOpenListener { - /** - * Called when mState.forcePluginOpen is changed - */ - void onChange(boolean forceOpen); - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java index 42222d724896..53cc2676723c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java @@ -44,6 +44,7 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.DragDownHelper; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.SuperStatusBarViewFactory; import com.android.systemui.statusbar.SysuiStatusBarStateController; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 686b87127239..11d05830d065 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -46,6 +46,7 @@ import com.android.systemui.DejankUtils; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dock.DockManager; import com.android.systemui.statusbar.BlurUtils; import com.android.systemui.statusbar.ScrimView; @@ -62,13 +63,12 @@ import java.lang.annotation.RetentionPolicy; import java.util.function.Consumer; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controls both the scrim behind the notifications and in front of the notifications (when a * security method gets shown). */ -@Singleton +@SysUISingleton public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnColorsChangedListener, Dumpable { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java index 333061547d7e..1ce22194878f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java @@ -23,20 +23,21 @@ import android.view.WindowManager; import com.android.systemui.assist.AssistManager; import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationPresenter; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.StatusBarState; import java.util.ArrayList; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; /** An implementation of {@link com.android.systemui.statusbar.phone.ShadeController}. */ -@Singleton +@SysUISingleton public class ShadeControllerImpl implements ShadeController { private static final String TAG = "ShadeControllerImpl"; 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 45fe56ee7e57..6e37f90f9d94 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -138,14 +138,12 @@ import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.ActivityIntentHelper; import com.android.systemui.AutoReinflateContainer; import com.android.systemui.DejankUtils; -import com.android.systemui.DemoMode; import com.android.systemui.Dumpable; import com.android.systemui.EventLogTags; import com.android.systemui.InitController; import com.android.systemui.Prefs; import com.android.systemui.R; import com.android.systemui.SystemUI; -import com.android.systemui.SystemUIFactory; import com.android.systemui.assist.AssistManager; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.bubbles.BubbleController; @@ -153,12 +151,16 @@ import com.android.systemui.charging.WirelessChargingAnimation; import com.android.systemui.classifier.FalsingLog; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dagger.qualifiers.UiBackground; +import com.android.systemui.demomode.DemoMode; +import com.android.systemui.demomode.DemoModeCommandReceiver; +import com.android.systemui.demomode.DemoModeController; import com.android.systemui.fragments.ExtensionFragmentListener; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.navigationbar.NavigationBarView; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.DarkIconDispatcher; @@ -183,12 +185,12 @@ import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.GestureRecorder; import com.android.systemui.statusbar.KeyboardShortcuts; import com.android.systemui.statusbar.KeyguardIndicationController; -import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.statusbar.NotificationLockscreenUserManager; 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.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.NotificationViewHierarchyManager; import com.android.systemui.statusbar.PulseExpansionHandler; @@ -201,8 +203,8 @@ import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationActivityStarter; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.init.NotificationsController; import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; @@ -233,6 +235,8 @@ import com.android.systemui.volume.VolumeComponent; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.Executor; @@ -391,12 +395,13 @@ public class StatusBar extends SystemUI implements DemoMode, private final SuperStatusBarViewFactory mSuperStatusBarViewFactory; private final LightsOutNotifController mLightsOutNotifController; private final InitController mInitController; - private final DarkIconDispatcher mDarkIconDispatcher; + private final PluginDependencyProvider mPluginDependencyProvider; private final KeyguardDismissUtil mKeyguardDismissUtil; private final ExtensionController mExtensionController; private final UserInfoControllerImpl mUserInfoControllerImpl; private final DismissCallbackRegistry mDismissCallbackRegistry; + private final DemoModeController mDemoModeController; private NotificationsController mNotificationsController; // expanded notifications @@ -603,7 +608,7 @@ public class StatusBar extends SystemUI implements DemoMode, private UiModeManager mUiModeManager; protected boolean mIsKeyguard; private LogMaker mStatusBarStateLog; - protected NotificationIconAreaController mNotificationIconAreaController; + protected final NotificationIconAreaController mNotificationIconAreaController; @Nullable private View mAmbientIndicationContainer; private final SysuiColorExtractor mColorExtractor; private final ScreenLifecycle mScreenLifecycle; @@ -725,7 +730,6 @@ public class StatusBar extends SystemUI implements DemoMode, StatusBarKeyguardViewManager statusBarKeyguardViewManager, ViewMediatorCallback viewMediatorCallback, InitController initController, - DarkIconDispatcher darkIconDispatcher, @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler, PluginDependencyProvider pluginDependencyProvider, KeyguardDismissUtil keyguardDismissUtil, @@ -734,8 +738,10 @@ public class StatusBar extends SystemUI implements DemoMode, PhoneStatusBarPolicy phoneStatusBarPolicy, KeyguardIndicationController keyguardIndicationController, DismissCallbackRegistry dismissCallbackRegistry, + DemoModeController demoModeController, Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy, - StatusBarTouchableRegionManager statusBarTouchableRegionManager) { + StatusBarTouchableRegionManager statusBarTouchableRegionManager, + NotificationIconAreaController notificationIconAreaController) { super(context); mNotificationsController = notificationsController; mLightBarController = lightBarController; @@ -805,13 +811,14 @@ public class StatusBar extends SystemUI implements DemoMode, mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mKeyguardViewMediatorCallback = viewMediatorCallback; mInitController = initController; - mDarkIconDispatcher = darkIconDispatcher; mPluginDependencyProvider = pluginDependencyProvider; mKeyguardDismissUtil = keyguardDismissUtil; mExtensionController = extensionController; mUserInfoControllerImpl = userInfoControllerImpl; mIconPolicy = phoneStatusBarPolicy; mDismissCallbackRegistry = dismissCallbackRegistry; + mDemoModeController = demoModeController; + mNotificationIconAreaController = notificationIconAreaController; mBubbleExpandListener = (isExpanding, key) -> { @@ -866,6 +873,9 @@ public class StatusBar extends SystemUI implements DemoMode, // Connect in to the status bar manager service mCommandQueue.addCallback(this); + // Listen for demo mode changes + mDemoModeController.addCallback(this); + RegisterStatusBarResult result = null; try { result = mBarService.registerStatusBar(mCommandQueue); @@ -942,9 +952,12 @@ public class StatusBar extends SystemUI implements DemoMode, startKeyguard(); mKeyguardUpdateMonitor.registerCallback(mUpdateCallback); - mDozeServiceHost.initialize(this, mNotificationIconAreaController, - mStatusBarKeyguardViewManager, mNotificationShadeWindowViewController, - mNotificationPanelViewController, mAmbientIndicationContainer); + mDozeServiceHost.initialize( + this, + mStatusBarKeyguardViewManager, + mNotificationShadeWindowViewController, + mNotificationPanelViewController, + mAmbientIndicationContainer); mConfigurationController.addCallback(this); @@ -1026,20 +1039,12 @@ public class StatusBar extends SystemUI implements DemoMode, mStackScrollerController.getNotificationListContainer(); mNotificationLogger.setUpWithContainer(notifListContainer); - // TODO: make this injectable. Currently that would create a circular dependency between - // NotificationIconAreaController and StatusBar. - mNotificationIconAreaController = SystemUIFactory.getInstance() - .createNotificationIconAreaController(context, this, - mWakeUpCoordinator, mKeyguardBypassController, - mStatusBarStateController); - mWakeUpCoordinator.setIconAreaController(mNotificationIconAreaController); + updateAodIconArea(); inflateShelf(); mNotificationIconAreaController.setupShelf(mNotificationShelfController); - mNotificationPanelViewController.setOnReinflationListener( - mNotificationIconAreaController::initAodIcons); + mNotificationPanelViewController.setOnReinflationListener(this::updateAodIconArea); mNotificationPanelViewController.addExpansionListener(mWakeUpCoordinator); - mDarkIconDispatcher.addDarkReceiver(mNotificationIconAreaController); // Allow plugins to reference DarkIconDispatcher and StatusBarStateController mPluginDependencyProvider.allowPluginDependency(DarkIconDispatcher.class); mPluginDependencyProvider.allowPluginDependency(StatusBarStateController.class); @@ -1152,9 +1157,11 @@ public class StatusBar extends SystemUI implements DemoMode, }); mScrimController.attachViews(scrimBehind, scrimInFront, scrimForBubble); - mNotificationPanelViewController.initDependencies(this, mGroupManager, + mNotificationPanelViewController.initDependencies( + this, + mGroupManager, mNotificationShelfController, - mNotificationIconAreaController, mScrimController); + mScrimController); BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop); mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front), @@ -1254,7 +1261,6 @@ public class StatusBar extends SystemUI implements DemoMode, if (DEBUG_MEDIA_FAKE_ARTWORK) { demoFilter.addAction(ACTION_FAKE_ARTWORK); } - demoFilter.addAction(ACTION_DEMO); context.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter, android.Manifest.permission.DUMP, null); @@ -1269,6 +1275,12 @@ public class StatusBar extends SystemUI implements DemoMode, ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f)); } + private void updateAodIconArea() { + mNotificationIconAreaController.setupAodIcons( + getNotificationShadeWindowView() + .findViewById(R.id.clock_notification_icon_container)); + } + @NonNull @Override public Lifecycle getLifecycle() { @@ -1464,6 +1476,34 @@ public class StatusBar extends SystemUI implements DemoMode, protected void startKeyguard() { Trace.beginSection("StatusBar#startKeyguard"); mBiometricUnlockController = mBiometricUnlockControllerLazy.get(); + mBiometricUnlockController.setBiometricModeListener( + new BiometricUnlockController.BiometricModeListener() { + @Override + public void onResetMode() { + setWakeAndUnlocking(false); + } + + @Override + public void onModeChanged(int mode) { + switch (mode) { + case BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM: + case BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING: + case BiometricUnlockController.MODE_WAKE_AND_UNLOCK: + setWakeAndUnlocking(true); + } + } + + @Override + public void notifyBiometricAuthModeChanged() { + StatusBar.this.notifyBiometricAuthModeChanged(); + } + + private void setWakeAndUnlocking(boolean wakeAndUnlocking) { + if (getNavigationBarView() != null) { + getNavigationBarView().setWakeAndUnlocking(wakeAndUnlocking); + } + } + }); mStatusBarKeyguardViewManager.registerStatusBar( /* statusBar= */ this, getBouncerContainer(), mNotificationPanelViewController, mBiometricUnlockController, @@ -1809,7 +1849,7 @@ public class StatusBar extends SystemUI implements DemoMode, mPanelExpanded = isExpanded; updateHideIconsForBouncer(false /* animate */); mNotificationShadeWindowController.setPanelExpanded(isExpanded); - mVisualStabilityManager.setPanelExpanded(isExpanded); + mStatusBarStateController.setPanelExpanded(isExpanded); if (isExpanded && mStatusBarStateController.getState() != StatusBarState.KEYGUARD) { if (DEBUG) { Log.v(TAG, "clearing notification effects from setExpandedHeight"); @@ -2030,7 +2070,7 @@ public class StatusBar extends SystemUI implements DemoMode, mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK); } mNotificationPanelViewController.expand(true /* animate */); - ((NotificationListContainer) mStackScroller).setWillExpand(true); + mStackScroller.setWillExpand(true); mHeadsUpManager.unpinAll(true /* userUnpinned */); mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN, 1); } else if (!mNotificationPanelViewController.isInSettings() @@ -2440,7 +2480,7 @@ public class StatusBar extends SystemUI implements DemoMode, } public void checkBarModes() { - if (mDemoMode) return; + if (mDemoModeController.isInDemoMode()) return; if (mNotificationShadeWindowViewController != null && getStatusBarTransitions() != null) { checkBarMode(mStatusBarMode, mStatusBarWindowState, getStatusBarTransitions()); } @@ -2813,19 +2853,7 @@ public class StatusBar extends SystemUI implements DemoMode, public void onReceive(Context context, Intent intent) { if (DEBUG) Log.v(TAG, "onReceive: " + intent); String action = intent.getAction(); - if (ACTION_DEMO.equals(action)) { - Bundle bundle = intent.getExtras(); - if (bundle != null) { - String command = bundle.getString("command", "").trim().toLowerCase(); - if (command.length() > 0) { - try { - dispatchDemoCommand(command, bundle); - } catch (Throwable t) { - Log.w(TAG, "Error running demo command, intent=" + intent, t); - } - } - } - } else if (ACTION_FAKE_ARTWORK.equals(action)) { + if (ACTION_FAKE_ARTWORK.equals(action)) { if (DEBUG_MEDIA_FAKE_ARTWORK) { mPresenter.updateMediaMetaData(true, true); } @@ -3089,50 +3117,34 @@ public class StatusBar extends SystemUI implements DemoMode, startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */); } - private boolean mDemoModeAllowed; - private boolean mDemoMode; + @Override + public List<String> demoCommands() { + List<String> s = new ArrayList<>(); + s.add(DemoMode.COMMAND_BARS); + s.add(DemoMode.COMMAND_CLOCK); + s.add(DemoMode.COMMAND_OPERATOR); + return s; + } @Override - public void dispatchDemoCommand(String command, Bundle args) { - if (!mDemoModeAllowed) { - mDemoModeAllowed = Settings.Global.getInt(mContext.getContentResolver(), - DEMO_MODE_ALLOWED, 0) != 0; - } - if (!mDemoModeAllowed) return; - if (command.equals(COMMAND_ENTER)) { - mDemoMode = true; - } else if (command.equals(COMMAND_EXIT)) { - mDemoMode = false; - checkBarModes(); - } else if (!mDemoMode) { - // automatically enter demo mode on first demo command - dispatchDemoCommand(COMMAND_ENTER, new Bundle()); - } - boolean modeChange = command.equals(COMMAND_ENTER) || command.equals(COMMAND_EXIT); - if ((modeChange || command.equals(COMMAND_VOLUME)) && mVolumeComponent != null) { - mVolumeComponent.dispatchDemoCommand(command, args); - } - if (modeChange || command.equals(COMMAND_CLOCK)) { + public void onDemoModeStarted() { + // Must send this message to any view that we delegate to via dispatchDemoCommandToView + dispatchDemoModeStartedToView(R.id.clock); + dispatchDemoModeStartedToView(R.id.operator_name); + } + + @Override + public void onDemoModeFinished() { + dispatchDemoModeFinishedToView(R.id.clock); + dispatchDemoModeFinishedToView(R.id.operator_name); + checkBarModes(); + } + + @Override + public void dispatchDemoCommand(String command, @NonNull Bundle args) { + if (command.equals(COMMAND_CLOCK)) { dispatchDemoCommandToView(command, args, R.id.clock); } - if (modeChange || command.equals(COMMAND_BATTERY)) { - mBatteryController.dispatchDemoCommand(command, args); - } - if (modeChange || command.equals(COMMAND_STATUS)) { - ((StatusBarIconControllerImpl) mIconController).dispatchDemoCommand(command, args); - } - if (mNetworkController != null && (modeChange || command.equals(COMMAND_NETWORK))) { - mNetworkController.dispatchDemoCommand(command, args); - } - if (modeChange || command.equals(COMMAND_NOTIFICATIONS)) { - View notifications = mStatusBarView == null ? null - : mStatusBarView.findViewById(R.id.notification_icon_area); - if (notifications != null) { - String visible = args.getString("visible"); - int vis = mDemoMode && "false".equals(visible) ? View.INVISIBLE : View.VISIBLE; - notifications.setVisibility(vis); - } - } if (command.equals(COMMAND_BARS)) { String mode = args.getString("mode"); int barMode = "opaque".equals(mode) ? MODE_OPAQUE : @@ -3151,16 +3163,33 @@ public class StatusBar extends SystemUI implements DemoMode, mNavigationBarController.transitionTo(mDisplayId, barMode, animate); } } - if (modeChange || command.equals(COMMAND_OPERATOR)) { + if (command.equals(COMMAND_OPERATOR)) { dispatchDemoCommandToView(command, args, R.id.operator_name); } } + //TODO: these should have controllers, and this method should be removed private void dispatchDemoCommandToView(String command, Bundle args, int id) { if (mStatusBarView == null) return; View v = mStatusBarView.findViewById(id); - if (v instanceof DemoMode) { - ((DemoMode)v).dispatchDemoCommand(command, args); + if (v instanceof DemoModeCommandReceiver) { + ((DemoModeCommandReceiver) v).dispatchDemoCommand(command, args); + } + } + + private void dispatchDemoModeStartedToView(int id) { + if (mStatusBarView == null) return; + View v = mStatusBarView.findViewById(id); + if (v instanceof DemoModeCommandReceiver) { + ((DemoModeCommandReceiver) v).onDemoModeStarted(); + } + } + + private void dispatchDemoModeFinishedToView(int id) { + if (mStatusBarView == null) return; + View v = mStatusBarView.findViewById(id); + if (v instanceof DemoModeCommandReceiver) { + ((DemoModeCommandReceiver) v).onDemoModeFinished(); } } @@ -3758,7 +3787,6 @@ public class StatusBar extends SystemUI implements DemoMode, mDeviceInteractive = false; mWakeUpComingFromTouch = false; mWakeUpTouchLocation = null; - mVisualStabilityManager.setScreenOn(false); updateVisibleToUser(); updateNotificationPanelTouchState(); @@ -3795,7 +3823,6 @@ public class StatusBar extends SystemUI implements DemoMode, if (!mKeyguardBypassController.getBypassEnabled()) { mHeadsUpManager.releaseAllImmediately(); } - mVisualStabilityManager.setScreenOn(true); updateVisibleToUser(); updateIsKeyguard(); mDozeServiceHost.stopDozing(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java index 8ff7a41cb22f..f0efed332c7f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java @@ -32,9 +32,9 @@ import android.widget.LinearLayout.LayoutParams; import androidx.annotation.VisibleForTesting; import com.android.internal.statusbar.StatusBarIcon; -import com.android.systemui.DemoMode; import com.android.systemui.Dependency; import com.android.systemui.R; +import com.android.systemui.demomode.DemoModeCommandReceiver; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.statusbar.CommandQueue; @@ -198,7 +198,7 @@ public interface StatusBarIconController { /** * Turns info from StatusBarIconController into ImageViews in a ViewGroup. */ - public static class IconManager implements DemoMode { + class IconManager implements DemoModeCommandReceiver { protected final ViewGroup mGroup; protected final Context mContext; protected final int mIconSize; @@ -390,18 +390,24 @@ public interface StatusBarIconController { return; } - if (command.equals(COMMAND_EXIT)) { - if (mDemoStatusIcons != null) { - mDemoStatusIcons.dispatchDemoCommand(command, args); - exitDemoMode(); - } + mDemoStatusIcons.dispatchDemoCommand(command, args); + } + + @Override + public void onDemoModeStarted() { + mIsInDemoMode = true; + if (mDemoStatusIcons == null) { + mDemoStatusIcons = createDemoStatusIcons(); + } + mDemoStatusIcons.onDemoModeStarted(); + } + + @Override + public void onDemoModeFinished() { + if (mDemoStatusIcons != null) { + mDemoStatusIcons.onDemoModeFinished(); + exitDemoMode(); mIsInDemoMode = false; - } else { - if (mDemoStatusIcons == null) { - mIsInDemoMode = true; - mDemoStatusIcons = createDemoStatusIcons(); - } - mDemoStatusIcons.dispatchDemoCommand(command, args); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java index 21e1d319cffa..2870152ed853 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java @@ -29,6 +29,9 @@ import com.android.internal.statusbar.StatusBarIcon; import com.android.systemui.Dependency; import com.android.systemui.Dumpable; import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.demomode.DemoMode; +import com.android.systemui.demomode.DemoModeController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.StatusIconDisplayable; import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState; @@ -45,31 +48,28 @@ import java.util.Collections; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * Receives the callbacks from CommandQueue related to icons and tracks the state of * all the icons. Dispatches this state to any IconManagers that are currently * registered with it. */ -@Singleton +@SysUISingleton public class StatusBarIconControllerImpl extends StatusBarIconList implements Tunable, - ConfigurationListener, Dumpable, CommandQueue.Callbacks, StatusBarIconController { + ConfigurationListener, Dumpable, CommandQueue.Callbacks, StatusBarIconController, DemoMode { private static final String TAG = "StatusBarIconController"; private final ArrayList<IconManager> mIconGroups = new ArrayList<>(); private final ArraySet<String> mIconHideList = new ArraySet<>(); - // Points to light or dark context depending on the... context? private Context mContext; - private Context mLightContext; - private Context mDarkContext; - - private boolean mIsDark = false; @Inject - public StatusBarIconControllerImpl(Context context, CommandQueue commandQueue) { + public StatusBarIconControllerImpl( + Context context, + CommandQueue commandQueue, + DemoModeController demoModeController) { super(context.getResources().getStringArray( com.android.internal.R.array.config_statusBarIcons)); Dependency.get(ConfigurationController.class).addCallback(this); @@ -80,6 +80,7 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu commandQueue.addCallback(this); Dependency.get(TunerService.class).addTunable(this, ICON_HIDE_LIST); + demoModeController.addCallback(this); } @Override @@ -339,6 +340,25 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu super.dump(pw); } + @Override + public void onDemoModeStarted() { + for (IconManager manager : mIconGroups) { + if (manager.isDemoable()) { + manager.onDemoModeStarted(); + } + } + } + + @Override + public void onDemoModeFinished() { + for (IconManager manager : mIconGroups) { + if (manager.isDemoable()) { + manager.onDemoModeFinished(); + } + } + } + + @Override public void dispatchDemoCommand(String command, Bundle args) { for (IconManager manager : mIconGroups) { if (manager.isDemoable()) { @@ -348,6 +368,13 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu } @Override + public List<String> demoCommands() { + List<String> s = new ArrayList<>(); + s.add(DemoMode.COMMAND_STATUS); + return s; + } + + @Override public void onDensityOrFontScaleChanged() { loadDimens(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index f3a7c501f6e8..7ee501c681f9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -47,6 +47,7 @@ import com.android.keyguard.ViewMediatorCallback; import com.android.settingslib.animation.AppearAnimationUtils; import com.android.systemui.DejankUtils; import com.android.systemui.SystemUIFactory; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dock.DockManager; import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.navigationbar.NavigationModeController; @@ -56,6 +57,7 @@ import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.NotificationMediaManager; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; @@ -68,7 +70,6 @@ import java.io.PrintWriter; import java.util.ArrayList; import javax.inject.Inject; -import javax.inject.Singleton; /** * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back @@ -76,7 +77,7 @@ import javax.inject.Singleton; * which is in turn, reported to this class by the current * {@link com.android.keyguard.KeyguardViewBase}. */ -@Singleton +@SysUISingleton public class StatusBarKeyguardViewManager implements RemoteInputController.Callback, StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener, PanelExpansionListener, NavigationModeController.ModeChangedListener, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java index b9f94b37d7d3..de11c9023200 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -49,6 +49,7 @@ import com.android.systemui.ActivityIntentHelper; import com.android.systemui.EventLogTags; import com.android.systemui.assist.AssistManager; import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.plugins.ActivityStarter; @@ -72,14 +73,13 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.No import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; -import com.android.systemui.statusbar.notification.row.OnDismissCallback; +import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback; import com.android.systemui.statusbar.policy.HeadsUpUtil; import com.android.systemui.statusbar.policy.KeyguardStateController; import java.util.concurrent.Executor; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; @@ -124,7 +124,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit private final NotificationPresenter mPresenter; private final NotificationPanelViewController mNotificationPanel; private final ActivityLaunchAnimator mActivityLaunchAnimator; - private final OnDismissCallback mOnDismissCallback; + private final OnUserInteractionCallback mOnUserInteractionCallback; private boolean mIsCollapsingToShowActivityOverLockscreen; @@ -158,7 +158,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit FeatureFlags featureFlags, MetricsLogger metricsLogger, StatusBarNotificationActivityStarterLogger logger, - OnDismissCallback onDismissCallback, + OnUserInteractionCallback onUserInteractionCallback, StatusBar statusBar, NotificationPresenter presenter, @@ -193,7 +193,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mFeatureFlags = featureFlags; mMetricsLogger = metricsLogger; mLogger = logger; - mOnDismissCallback = onDismissCallback; + mOnUserInteractionCallback = onUserInteractionCallback; // TODO: use KeyguardStateController#isOccluded to remove this dependency mStatusBar = statusBar; @@ -575,10 +575,10 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit // To avoid lags we're only performing the remove // after the shade was collapsed mShadeController.addPostCollapseAction( - () -> mOnDismissCallback.onDismiss(entry, REASON_CLICK) + () -> mOnUserInteractionCallback.onDismiss(entry, REASON_CLICK) ); } else { - mOnDismissCallback.onDismiss(entry, REASON_CLICK); + mOnUserInteractionCallback.onDismiss(entry, REASON_CLICK); } }); } @@ -596,7 +596,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit /** * Public builder for {@link StatusBarNotificationActivityStarter}. */ - @Singleton + @SysUISingleton public static class Builder { private final Context mContext; private final CommandQueue mCommandQueue; @@ -628,7 +628,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit private final FeatureFlags mFeatureFlags; private final MetricsLogger mMetricsLogger; private final StatusBarNotificationActivityStarterLogger mLogger; - private final OnDismissCallback mOnDismissCallback; + private final OnUserInteractionCallback mOnUserInteractionCallback; private StatusBar mStatusBar; private NotificationPresenter mNotificationPresenter; @@ -666,7 +666,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit FeatureFlags featureFlags, MetricsLogger metricsLogger, StatusBarNotificationActivityStarterLogger logger, - OnDismissCallback onDismissCallback) { + OnUserInteractionCallback onUserInteractionCallback) { mContext = context; mCommandQueue = commandQueue; @@ -697,7 +697,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mFeatureFlags = featureFlags; mMetricsLogger = metricsLogger; mLogger = logger; - mOnDismissCallback = onDismissCallback; + mOnUserInteractionCallback = onUserInteractionCallback; } /** Sets the status bar to use as {@link StatusBar}. */ @@ -754,7 +754,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mFeatureFlags, mMetricsLogger, mLogger, - mOnDismissCallback, + mOnUserInteractionCallback, mStatusBar, mNotificationPresenter, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java index f1715bef62d2..67adaaae402e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java @@ -52,6 +52,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationViewHierarchyManager; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; @@ -60,9 +61,9 @@ import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; @@ -216,7 +217,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter, notificationInterruptStateProvider.addSuppressor(mInterruptSuppressor); mLockscreenUserManager.setUpWithPresenter(this); mMediaManager.setUpWithPresenter(this); - mVisualStabilityManager.setUpWithPresenter(this); mGutsManager.setUpWithPresenter(this, stackScrollerController.getNotificationListContainer(), mCheckSaveListener, mOnSettingsClickListener); 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 ac69d9c32c93..8a8942975d2e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java @@ -34,6 +34,7 @@ import android.view.View; import android.view.ViewParent; import com.android.systemui.ActivityIntentHelper; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.ActionClickLogger; @@ -49,11 +50,10 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll import com.android.systemui.statusbar.policy.KeyguardStateController; import javax.inject.Inject; -import javax.inject.Singleton; /** */ -@Singleton +@SysUISingleton public class StatusBarRemoteInputCallback implements Callback, Callbacks, StatusBarStateController.StateListener { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java index 9c7f49090122..b859250a2442 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java @@ -32,6 +32,8 @@ import android.view.WindowInsets; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.ScreenDecorations; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; @@ -40,14 +42,13 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import javax.inject.Inject; -import javax.inject.Singleton; /** * Manages what parts of the status bar are touchable. Clients are primarily UI that display in the * status bar even though the UI doesn't look like part of the status bar. Currently this consists * of HeadsUpNotifications. */ -@Singleton +@SysUISingleton public final class StatusBarTouchableRegionManager implements Dumpable { private static final String TAG = "TouchableRegionManager"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java index d4e1aa4d3d27..2f7278b38d15 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java @@ -29,16 +29,16 @@ import android.view.Gravity; import android.view.ViewGroup; import android.view.WindowManager; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.SuperStatusBarViewFactory; import javax.inject.Inject; -import javax.inject.Singleton; /** * Encapsulates all logic for the status bar window state management. */ -@Singleton +@SysUISingleton public class StatusBarWindowController { private static final String TAG = "StatusBarWindowController"; private static final boolean DEBUG = false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneDependenciesModule.java index 69c6814090d1..79d72b3d0f65 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneDependenciesModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneDependenciesModule.java @@ -16,12 +16,11 @@ package com.android.systemui.statusbar.phone.dagger; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.row.RowContentBindStage; import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper; import com.android.systemui.statusbar.phone.StatusBar; -import javax.inject.Singleton; - import dagger.Module; import dagger.Provides; @@ -34,7 +33,7 @@ import dagger.Provides; public interface StatusBarPhoneDependenciesModule { /** */ - @Singleton + @SysUISingleton @Provides static NotificationGroupAlertTransferHelper provideNotificationGroupAlertTransferHelper( RowContentBindStage bindStage) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java index eb2ae71500c5..2768b826fcfe 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java @@ -33,12 +33,14 @@ import com.android.systemui.assist.AssistManager; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.UiBackground; +import com.android.systemui.demomode.DemoModeController; import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; -import com.android.systemui.plugins.DarkIconDispatcher; +import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.PluginDependencyProvider; import com.android.systemui.recents.Recents; @@ -47,11 +49,11 @@ import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.stackdivider.Divider; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.KeyguardIndicationController; -import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationViewHierarchyManager; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.SuperStatusBarViewFactory; @@ -59,7 +61,7 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; -import com.android.systemui.statusbar.notification.VisualStabilityManager; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.init.NotificationsController; import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; @@ -79,7 +81,7 @@ import com.android.systemui.statusbar.phone.LightsOutNotifController; import com.android.systemui.statusbar.phone.LockscreenLockIconController; import com.android.systemui.statusbar.phone.LockscreenWallpaper; import com.android.systemui.statusbar.phone.NotificationGroupManager; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; +import com.android.systemui.statusbar.phone.NotificationIconAreaController; import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ShadeController; @@ -104,7 +106,6 @@ import java.util.concurrent.Executor; import javax.inject.Named; import javax.inject.Provider; -import javax.inject.Singleton; import dagger.Lazy; import dagger.Module; @@ -119,7 +120,7 @@ public interface StatusBarPhoneModule { * Provides our instance of StatusBar which is considered optional. */ @Provides - @Singleton + @SysUISingleton static StatusBar provideStatusBar( Context context, NotificationsController notificationsController, @@ -188,7 +189,6 @@ public interface StatusBarPhoneModule { StatusBarKeyguardViewManager statusBarKeyguardViewManager, ViewMediatorCallback viewMediatorCallback, InitController initController, - DarkIconDispatcher darkIconDispatcher, @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler, PluginDependencyProvider pluginDependencyProvider, KeyguardDismissUtil keyguardDismissUtil, @@ -196,9 +196,11 @@ public interface StatusBarPhoneModule { UserInfoControllerImpl userInfoControllerImpl, PhoneStatusBarPolicy phoneStatusBarPolicy, KeyguardIndicationController keyguardIndicationController, + DemoModeController demoModeController, Lazy<NotificationShadeDepthController> notificationShadeDepthController, DismissCallbackRegistry dismissCallbackRegistry, - StatusBarTouchableRegionManager statusBarTouchableRegionManager) { + StatusBarTouchableRegionManager statusBarTouchableRegionManager, + NotificationIconAreaController notificationIconAreaController) { return new StatusBar( context, notificationsController, @@ -266,7 +268,6 @@ public interface StatusBarPhoneModule { statusBarKeyguardViewManager, viewMediatorCallback, initController, - darkIconDispatcher, timeTickHandler, pluginDependencyProvider, keyguardDismissUtil, @@ -275,7 +276,9 @@ public interface StatusBarPhoneModule { phoneStatusBarPolicy, keyguardIndicationController, dismissCallbackRegistry, + demoModeController, notificationShadeDepthController, - statusBarTouchableRegionManager); + statusBarTouchableRegionManager, + notificationIconAreaController); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java index ebfdb3f9aa76..ad49c796f91d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java @@ -19,16 +19,17 @@ package com.android.systemui.statusbar.policy; import android.content.Context; import android.view.accessibility.AccessibilityManager; +import com.android.systemui.dagger.SysUISingleton; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import javax.inject.Inject; -import javax.inject.Singleton; /** */ -@Singleton +@SysUISingleton public class AccessibilityController implements AccessibilityManager.AccessibilityStateChangeListener, AccessibilityManager.TouchExplorationStateChangeListener { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java index 1395e1377529..d38284a26a07 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java @@ -19,13 +19,16 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener; +import androidx.annotation.NonNull; + +import com.android.systemui.dagger.SysUISingleton; + import javax.inject.Inject; -import javax.inject.Singleton; /** * For mocking because AccessibilityManager is final for some reason... */ -@Singleton +@SysUISingleton public class AccessibilityManagerWrapper implements CallbackController<AccessibilityServicesStateChangeListener> { @@ -37,12 +40,12 @@ public class AccessibilityManagerWrapper implements } @Override - public void addCallback(AccessibilityServicesStateChangeListener listener) { + public void addCallback(@NonNull AccessibilityServicesStateChangeListener listener) { mAccessibilityManager.addAccessibilityServicesStateChangeListener(listener, null); } @Override - public void removeCallback(AccessibilityServicesStateChangeListener listener) { + public void removeCallback(@NonNull AccessibilityServicesStateChangeListener listener) { mAccessibilityManager.removeAccessibilityServicesStateChangeListener(listener); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java index e5a46797d035..06e4731265e3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java @@ -18,8 +18,8 @@ package com.android.systemui.statusbar.policy; import android.annotation.Nullable; -import com.android.systemui.DemoMode; import com.android.systemui.Dumpable; +import com.android.systemui.demomode.DemoMode; import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; import java.io.FileDescriptor; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java index 88a6263c1dca..57ac85e1e86d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java @@ -27,6 +27,7 @@ import android.os.PowerManager; import android.os.PowerSaveState; import android.util.Log; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; @@ -34,22 +35,25 @@ import com.android.settingslib.fuelgauge.BatterySaverUtils; import com.android.settingslib.fuelgauge.Estimate; import com.android.settingslib.utils.PowerUtil; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.demomode.DemoMode; +import com.android.systemui.demomode.DemoModeController; import com.android.systemui.power.EnhancedEstimates; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * Default implementation of a {@link BatteryController}. This controller monitors for battery * level change events that are broadcasted by the system. */ -@Singleton +@SysUISingleton public class BatteryControllerImpl extends BroadcastReceiver implements BatteryController { private static final String TAG = "BatteryController"; @@ -63,6 +67,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC mChangeCallbacks = new ArrayList<>(); private final ArrayList<EstimateFetchCompletion> mFetchCallbacks = new ArrayList<>(); private final PowerManager mPowerManager; + private final DemoModeController mDemoModeController; private final Handler mMainHandler; private final Handler mBgHandler; protected final Context mContext; @@ -82,15 +87,21 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC @VisibleForTesting @Inject - public BatteryControllerImpl(Context context, EnhancedEstimates enhancedEstimates, - PowerManager powerManager, BroadcastDispatcher broadcastDispatcher, - @Main Handler mainHandler, @Background Handler bgHandler) { + public BatteryControllerImpl( + Context context, + EnhancedEstimates enhancedEstimates, + PowerManager powerManager, + BroadcastDispatcher broadcastDispatcher, + DemoModeController demoModeController, + @Main Handler mainHandler, + @Background Handler bgHandler) { mContext = context; mMainHandler = mainHandler; mBgHandler = bgHandler; mPowerManager = powerManager; mEstimates = enhancedEstimates; mBroadcastDispatcher = broadcastDispatcher; + mDemoModeController = demoModeController; } private void registerReceiver() { @@ -114,6 +125,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC onReceive(mContext, intent); } } + mDemoModeController.addCallback(this); updatePowerSave(); updateEstimate(); } @@ -134,7 +146,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC } @Override - public void addCallback(BatteryController.BatteryStateChangeCallback cb) { + public void addCallback(@NonNull BatteryController.BatteryStateChangeCallback cb) { synchronized (mChangeCallbacks) { mChangeCallbacks.add(cb); } @@ -144,7 +156,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC } @Override - public void removeCallback(BatteryController.BatteryStateChangeCallback cb) { + public void removeCallback(@NonNull BatteryController.BatteryStateChangeCallback cb) { synchronized (mChangeCallbacks) { mChangeCallbacks.remove(cb); } @@ -325,32 +337,43 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC } } - private boolean mDemoMode; - @Override public void dispatchDemoCommand(String command, Bundle args) { - if (!mDemoMode && command.equals(COMMAND_ENTER)) { - mDemoMode = true; - mBroadcastDispatcher.unregisterReceiver(this); - } else if (mDemoMode && command.equals(COMMAND_EXIT)) { - mDemoMode = false; - registerReceiver(); - updatePowerSave(); - } else if (mDemoMode && command.equals(COMMAND_BATTERY)) { - String level = args.getString("level"); - String plugged = args.getString("plugged"); - String powerSave = args.getString("powersave"); - if (level != null) { - mLevel = Math.min(Math.max(Integer.parseInt(level), 0), 100); - } - if (plugged != null) { - mPluggedIn = Boolean.parseBoolean(plugged); - } - if (powerSave != null) { - mPowerSave = powerSave.equals("true"); - firePowerSaveChanged(); - } - fireBatteryLevelChanged(); + if (!mDemoModeController.isInDemoMode()) { + return; + } + + String level = args.getString("level"); + String plugged = args.getString("plugged"); + String powerSave = args.getString("powersave"); + if (level != null) { + mLevel = Math.min(Math.max(Integer.parseInt(level), 0), 100); + } + if (plugged != null) { + mPluggedIn = Boolean.parseBoolean(plugged); + } + if (powerSave != null) { + mPowerSave = powerSave.equals("true"); + firePowerSaveChanged(); } + fireBatteryLevelChanged(); + } + + @Override + public List<String> demoCommands() { + List<String> s = new ArrayList<>(); + s.add(DemoMode.COMMAND_BATTERY); + return s; + } + + @Override + public void onDemoModeStarted() { + mBroadcastDispatcher.unregisterReceiver(this); + } + + @Override + public void onDemoModeFinished() { + registerReceiver(); + updatePowerSave(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java index 0fc3d8481907..33b1a4a880ae 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java @@ -29,11 +29,14 @@ import android.os.UserHandle; import android.os.UserManager; import android.util.Log; +import androidx.annotation.NonNull; + import com.android.settingslib.bluetooth.BluetoothCallback; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfile; import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; @@ -46,11 +49,10 @@ import java.util.List; import java.util.WeakHashMap; import javax.inject.Inject; -import javax.inject.Singleton; /** */ -@Singleton +@SysUISingleton public class BluetoothControllerImpl implements BluetoothController, BluetoothCallback, CachedBluetoothDevice.Callback, LocalBluetoothProfileManager.ServiceListener { private static final String TAG = "BluetoothController"; @@ -150,13 +152,13 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa } @Override - public void addCallback(Callback cb) { + public void addCallback(@NonNull Callback cb) { mHandler.obtainMessage(H.MSG_ADD_CALLBACK, cb).sendToTarget(); mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); } @Override - public void removeCallback(Callback cb) { + public void removeCallback(@NonNull Callback cb) { mHandler.obtainMessage(H.MSG_REMOVE_CALLBACK, cb).sendToTarget(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java index 78111fb61fd0..a0b03e1c54c2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java @@ -123,13 +123,13 @@ public class BrightnessMirrorController } @Override - public void addCallback(BrightnessMirrorListener listener) { + public void addCallback(@NonNull BrightnessMirrorListener listener) { Objects.requireNonNull(listener); mBrightnessMirrorListeners.add(listener); } @Override - public void removeCallback(BrightnessMirrorListener listener) { + public void removeCallback(@NonNull BrightnessMirrorListener listener) { mBrightnessMirrorListeners.remove(listener); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackController.java index 626eef5867f2..047ff75468ed 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackController.java @@ -15,14 +15,19 @@ package com.android.systemui.statusbar.policy; +import androidx.annotation.NonNull; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.Lifecycle.Event; import androidx.lifecycle.LifecycleEventObserver; import androidx.lifecycle.LifecycleOwner; public interface CallbackController<T> { - void addCallback(T listener); - void removeCallback(T listener); + + /** Add a callback */ + void addCallback(@NonNull T listener); + + /** Remove a callback */ + void removeCallback(@NonNull T listener); /** * Wrapper to {@link #addCallback(Object)} when a lifecycle is in the resumed state diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java index 6106f38c0e60..7bde31592965 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java @@ -31,10 +31,12 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import com.android.internal.annotations.GuardedBy; import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; import com.android.systemui.util.Utils; @@ -46,11 +48,10 @@ import java.util.Objects; import java.util.UUID; import javax.inject.Inject; -import javax.inject.Singleton; /** Platform implementation of the cast controller. **/ -@Singleton +@SysUISingleton public class CastControllerImpl implements CastController { private static final String TAG = "CastController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @@ -95,7 +96,7 @@ public class CastControllerImpl implements CastController { } @Override - public void addCallback(Callback callback) { + public void addCallback(@NonNull Callback callback) { synchronized (mCallbacks) { mCallbacks.add(callback); } @@ -106,7 +107,7 @@ public class CastControllerImpl implements CastController { } @Override - public void removeCallback(Callback callback) { + public void removeCallback(@NonNull Callback callback) { synchronized (mCallbacks) { mCallbacks.remove(callback); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java index 120a0e3abba4..ef35a3c55ab8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java @@ -40,11 +40,11 @@ import android.view.View; import android.widget.TextView; import com.android.settingslib.Utils; -import com.android.systemui.DemoMode; import com.android.systemui.Dependency; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.demomode.DemoModeCommandReceiver; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.settings.CurrentUserTracker; @@ -62,7 +62,10 @@ import java.util.TimeZone; /** * Digital clock for the status bar. */ -public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.Callbacks, +public class Clock extends TextView implements + DemoModeCommandReceiver, + Tunable, + CommandQueue.Callbacks, DarkReceiver, ConfigurationListener { public static final String CLOCK_SECONDS = "clock_seconds"; @@ -467,30 +470,35 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C @Override public void dispatchDemoCommand(String command, Bundle args) { - if (!mDemoMode && command.equals(COMMAND_ENTER)) { - mDemoMode = true; - } else if (mDemoMode && command.equals(COMMAND_EXIT)) { - mDemoMode = false; - updateClock(); - } else if (mDemoMode && command.equals(COMMAND_CLOCK)) { - String millis = args.getString("millis"); - String hhmm = args.getString("hhmm"); - if (millis != null) { - mCalendar.setTimeInMillis(Long.parseLong(millis)); - } else if (hhmm != null && hhmm.length() == 4) { - int hh = Integer.parseInt(hhmm.substring(0, 2)); - int mm = Integer.parseInt(hhmm.substring(2)); - boolean is24 = DateFormat.is24HourFormat(getContext(), mCurrentUserId); - if (is24) { - mCalendar.set(Calendar.HOUR_OF_DAY, hh); - } else { - mCalendar.set(Calendar.HOUR, hh); - } - mCalendar.set(Calendar.MINUTE, mm); + // Only registered for COMMAND_CLOCK + String millis = args.getString("millis"); + String hhmm = args.getString("hhmm"); + if (millis != null) { + mCalendar.setTimeInMillis(Long.parseLong(millis)); + } else if (hhmm != null && hhmm.length() == 4) { + int hh = Integer.parseInt(hhmm.substring(0, 2)); + int mm = Integer.parseInt(hhmm.substring(2)); + boolean is24 = DateFormat.is24HourFormat(getContext(), mCurrentUserId); + if (is24) { + mCalendar.set(Calendar.HOUR_OF_DAY, hh); + } else { + mCalendar.set(Calendar.HOUR, hh); } - setText(getSmallTime()); - setContentDescription(mContentDescriptionFormat.format(mCalendar.getTime())); + mCalendar.set(Calendar.MINUTE, mm); } + setText(getSmallTime()); + setContentDescription(mContentDescriptionFormat.format(mCalendar.getTime())); + } + + @Override + public void onDemoModeStarted() { + mDemoMode = true; + } + + @Override + public void onDemoModeFinished() { + mDemoMode = false; + updateClock(); } private final BroadcastReceiver mScreenReceiver = new BroadcastReceiver() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java index 911715fdba63..8207012af6cc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java @@ -21,6 +21,8 @@ import android.os.Handler; import android.os.Looper; import android.os.RemoteException; +import androidx.annotation.NonNull; + import java.util.ArrayList; public class DataSaverControllerImpl implements DataSaverController { @@ -41,7 +43,8 @@ public class DataSaverControllerImpl implements DataSaverController { } } - public void addCallback(Listener listener) { + @Override + public void addCallback(@NonNull Listener listener) { synchronized (mListeners) { mListeners.add(listener); if (mListeners.size() == 1) { @@ -51,7 +54,8 @@ public class DataSaverControllerImpl implements DataSaverController { listener.onDataSaverChanged(isDataSaverEnabled()); } - public void removeCallback(Listener listener) { + @Override + public void removeCallback(@NonNull Listener listener) { synchronized (mListeners) { mListeners.remove(listener); if (mListeners.size() == 0) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java index 7280a881655c..9b4e16525df2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java @@ -24,18 +24,20 @@ import android.provider.Settings.Global; import android.provider.Settings.Secure; import android.util.Log; +import androidx.annotation.NonNull; + import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.settings.CurrentUserTracker; import java.util.ArrayList; import javax.inject.Inject; -import javax.inject.Singleton; /** */ -@Singleton +@SysUISingleton public class DeviceProvisionedControllerImpl extends CurrentUserTracker implements DeviceProvisionedController { @@ -87,7 +89,7 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen } @Override - public void addCallback(DeviceProvisionedListener listener) { + public void addCallback(@NonNull DeviceProvisionedListener listener) { mListeners.add(listener); if (mListeners.size() == 1) { startListening(getCurrentUser()); @@ -97,7 +99,7 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen } @Override - public void removeCallback(DeviceProvisionedListener listener) { + public void removeCallback(@NonNull DeviceProvisionedListener listener) { mListeners.remove(listener); if (mListeners.size() == 0) { stopListening(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java index eeef726ace75..5011d96d57f8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java @@ -19,6 +19,7 @@ import android.content.res.Configuration; import android.os.Handler; import android.util.ArrayMap; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.Plugin; import com.android.systemui.plugins.PluginListener; import com.android.systemui.shared.plugins.PluginManager; @@ -34,11 +35,10 @@ import java.util.function.Consumer; import java.util.function.Supplier; import javax.inject.Inject; -import javax.inject.Singleton; /** */ -@Singleton +@SysUISingleton public class ExtensionControllerImpl implements ExtensionController { public static final int SORT_ORDER_PLUGIN = 0; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java index 41ff9d1029b2..d7c2b9664011 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java @@ -30,18 +30,21 @@ import android.provider.Settings.Secure; import android.text.TextUtils; import android.util.Log; +import androidx.annotation.NonNull; + +import com.android.systemui.dagger.SysUISingleton; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; import javax.inject.Inject; -import javax.inject.Singleton; /** * Manages the flashlight. */ -@Singleton +@SysUISingleton public class FlashlightControllerImpl implements FlashlightController { private static final String TAG = "FlashlightController"; @@ -123,7 +126,8 @@ public class FlashlightControllerImpl implements FlashlightController { return mTorchAvailable; } - public void addCallback(FlashlightListener l) { + @Override + public void addCallback(@NonNull FlashlightListener l) { synchronized (mListeners) { if (mCameraId == null) { tryInitCamera(); @@ -135,7 +139,8 @@ public class FlashlightControllerImpl implements FlashlightController { } } - public void removeCallback(FlashlightListener l) { + @Override + public void removeCallback(@NonNull FlashlightListener l) { synchronized (mListeners) { cleanUpListenersLocked(l); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java index 60ee75b534d8..99feb18b33e9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java @@ -30,7 +30,10 @@ import android.os.HandlerExecutor; import android.os.UserManager; import android.util.Log; +import androidx.annotation.NonNull; + import com.android.internal.util.ConcurrentUtils; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; @@ -40,12 +43,11 @@ import java.util.ArrayList; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controller used to retrieve information related to a hotspot. */ -@Singleton +@SysUISingleton public class HotspotControllerImpl implements HotspotController, WifiManager.SoftApCallback { private static final String TAG = "HotspotController"; @@ -143,7 +145,7 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof * changes. It will immediately trigger the callback added to notify current state. */ @Override - public void addCallback(Callback callback) { + public void addCallback(@NonNull Callback callback) { synchronized (mCallbacks) { if (callback == null || mCallbacks.contains(callback)) return; if (DEBUG) Log.d(TAG, "addCallback " + callback); @@ -163,7 +165,7 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof } @Override - public void removeCallback(Callback callback) { + public void removeCallback(@NonNull Callback callback) { if (callback == null) return; if (DEBUG) Log.d(TAG, "removeCallback " + callback); synchronized (mCallbacks) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java index a7f60d64c332..7f4eec745690 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java @@ -31,6 +31,7 @@ import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -38,11 +39,10 @@ import java.util.ArrayList; import java.util.Objects; import javax.inject.Inject; -import javax.inject.Singleton; /** */ -@Singleton +@SysUISingleton public class KeyguardStateControllerImpl implements KeyguardStateController, Dumpable { private static final boolean DEBUG_AUTH_WITH_ADB = false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java index adfc14e1d72b..0fdc80b3d97a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java @@ -33,12 +33,14 @@ import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import com.android.systemui.BootCompleteCache; import com.android.systemui.appops.AppOpItem; import com.android.systemui.appops.AppOpsController; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.util.Utils; @@ -47,12 +49,11 @@ import java.util.ArrayList; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * A controller to manage changes of location related states and update the views accordingly. */ -@Singleton +@SysUISingleton public class LocationControllerImpl extends BroadcastReceiver implements LocationController, AppOpsController.Callback { @@ -87,12 +88,14 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio /** * Add a callback to listen for changes in location settings. */ - public void addCallback(LocationChangeCallback cb) { + @Override + public void addCallback(@NonNull LocationChangeCallback cb) { mHandler.obtainMessage(H.MSG_ADD_CALLBACK, cb).sendToTarget(); mHandler.sendEmptyMessage(H.MSG_LOCATION_SETTINGS_CHANGED); } - public void removeCallback(LocationChangeCallback cb) { + @Override + public void removeCallback(@NonNull LocationChangeCallback cb) { mHandler.obtainMessage(H.MSG_REMOVE_CALLBACK, cb).sendToTarget(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 95a97729936b..b790c92b293c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -22,7 +22,7 @@ import android.telephony.SubscriptionInfo; import com.android.settingslib.net.DataUsageController; import com.android.settingslib.wifi.AccessPoint; -import com.android.systemui.DemoMode; +import com.android.systemui.demomode.DemoMode; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; import java.util.List; @@ -30,8 +30,6 @@ import java.util.List; public interface NetworkController extends CallbackController<SignalCallback>, DemoMode { boolean hasMobileDataFeature(); - void addCallback(SignalCallback cb); - void removeCallback(SignalCallback cb); void setWifiEnabled(boolean enabled); AccessPointController getAccessPointController(); DataUsageController getMobileDataController(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 32c4aec39923..2253ce7a62a3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -55,14 +55,18 @@ import android.util.Log; import android.util.MathUtils; import android.util.SparseArray; +import androidx.annotation.NonNull; + import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.settingslib.net.DataUsageController; -import com.android.systemui.DemoMode; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.demomode.DemoMode; +import com.android.systemui.demomode.DemoModeController; import com.android.systemui.settings.CurrentUserTracker; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; @@ -76,10 +80,9 @@ import java.util.List; import java.util.Locale; import javax.inject.Inject; -import javax.inject.Singleton; /** Platform implementation of the network controller. **/ -@Singleton +@SysUISingleton public class NetworkControllerImpl extends BroadcastReceiver implements NetworkController, DemoMode, DataUsageController.NetworkNameProvider, Dumpable { // debug @@ -104,6 +107,7 @@ public class NetworkControllerImpl extends BroadcastReceiver private final DataSaverController mDataSaverController; private final CurrentUserTracker mUserTracker; private final BroadcastDispatcher mBroadcastDispatcher; + private final DemoModeController mDemoModeController; private final Object mLock = new Object(); private Config mConfig; @@ -173,11 +177,16 @@ public class NetworkControllerImpl extends BroadcastReceiver * Construct this controller object and register for updates. */ @Inject - public NetworkControllerImpl(Context context, @Background Looper bgLooper, + public NetworkControllerImpl( + Context context, + @Background Looper bgLooper, DeviceProvisionedController deviceProvisionedController, - BroadcastDispatcher broadcastDispatcher, ConnectivityManager connectivityManager, - TelephonyManager telephonyManager, @Nullable WifiManager wifiManager, - NetworkScoreManager networkScoreManager) { + BroadcastDispatcher broadcastDispatcher, + ConnectivityManager connectivityManager, + TelephonyManager telephonyManager, + @Nullable WifiManager wifiManager, + NetworkScoreManager networkScoreManager, + DemoModeController demoModeController) { this(context, connectivityManager, telephonyManager, wifiManager, @@ -188,7 +197,8 @@ public class NetworkControllerImpl extends BroadcastReceiver new DataUsageController(context), new SubscriptionDefaults(), deviceProvisionedController, - broadcastDispatcher); + broadcastDispatcher, + demoModeController); mReceiverHandler.post(mRegisterListeners); } @@ -202,7 +212,8 @@ public class NetworkControllerImpl extends BroadcastReceiver DataUsageController dataUsageController, SubscriptionDefaults defaultsHandler, DeviceProvisionedController deviceProvisionedController, - BroadcastDispatcher broadcastDispatcher) { + BroadcastDispatcher broadcastDispatcher, + DemoModeController demoModeController) { mContext = context; mConfig = config; mReceiverHandler = new Handler(bgLooper); @@ -215,6 +226,7 @@ public class NetworkControllerImpl extends BroadcastReceiver mConnectivityManager = connectivityManager; mHasMobileDataFeature = mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); + mDemoModeController = demoModeController; // telephony mPhone = telephonyManager; @@ -306,6 +318,8 @@ public class NetworkControllerImpl extends BroadcastReceiver doUpdateMobileControllers(); } }; + + mDemoModeController.addCallback(this); } private final Runnable mClearForceValidated = () -> { @@ -514,7 +528,8 @@ public class NetworkControllerImpl extends BroadcastReceiver mCallbackHandler.setEmergencyCallsOnly(mIsEmergency); } - public void addCallback(SignalCallback cb) { + @Override + public void addCallback(@NonNull SignalCallback cb) { cb.setSubs(mCurrentSubscriptions); cb.setIsAirplaneMode(new IconState(mAirplaneMode, TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext)); @@ -529,7 +544,7 @@ public class NetworkControllerImpl extends BroadcastReceiver } @Override - public void removeCallback(SignalCallback cb) { + public void removeCallback(@NonNull SignalCallback cb) { mCallbackHandler.setListening(cb, false); } @@ -932,205 +947,217 @@ public class NetworkControllerImpl extends BroadcastReceiver return "UNKNOWN_SOURCE"; } - private boolean mDemoMode; private boolean mDemoInetCondition; private WifiSignalController.WifiState mDemoWifiState; @Override + public void onDemoModeStarted() { + if (DEBUG) Log.d(TAG, "Entering demo mode"); + unregisterListeners(); + mDemoInetCondition = mInetCondition; + mDemoWifiState = mWifiSignalController.getState(); + mDemoWifiState.ssid = "DemoMode"; + } + + @Override + public void onDemoModeFinished() { + if (DEBUG) Log.d(TAG, "Exiting demo mode"); + // Update what MobileSignalControllers, because they may change + // to set the number of sim slots. + updateMobileControllers(); + for (int i = 0; i < mMobileSignalControllers.size(); i++) { + MobileSignalController controller = mMobileSignalControllers.valueAt(i); + controller.resetLastState(); + } + mWifiSignalController.resetLastState(); + mReceiverHandler.post(mRegisterListeners); + notifyAllListeners(); + } + + @Override public void dispatchDemoCommand(String command, Bundle args) { - if (!mDemoMode && command.equals(COMMAND_ENTER)) { - if (DEBUG) Log.d(TAG, "Entering demo mode"); - unregisterListeners(); - mDemoMode = true; - mDemoInetCondition = mInetCondition; - mDemoWifiState = mWifiSignalController.getState(); - mDemoWifiState.ssid = "DemoMode"; - } else if (mDemoMode && command.equals(COMMAND_EXIT)) { - if (DEBUG) Log.d(TAG, "Exiting demo mode"); - mDemoMode = false; - // Update what MobileSignalControllers, because they may change - // to set the number of sim slots. - updateMobileControllers(); + if (!mDemoModeController.isInDemoMode()) { + return; + } + + String airplane = args.getString("airplane"); + if (airplane != null) { + boolean show = airplane.equals("show"); + mCallbackHandler.setIsAirplaneMode(new IconState(show, + TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, + mContext)); + } + String fully = args.getString("fully"); + if (fully != null) { + mDemoInetCondition = Boolean.parseBoolean(fully); + BitSet connected = new BitSet(); + + if (mDemoInetCondition) { + connected.set(mWifiSignalController.mTransportType); + } + mWifiSignalController.updateConnectivity(connected, connected); for (int i = 0; i < mMobileSignalControllers.size(); i++) { MobileSignalController controller = mMobileSignalControllers.valueAt(i); - controller.resetLastState(); - } - mWifiSignalController.resetLastState(); - mReceiverHandler.post(mRegisterListeners); - notifyAllListeners(); - } else if (mDemoMode && command.equals(COMMAND_NETWORK)) { - String airplane = args.getString("airplane"); - if (airplane != null) { - boolean show = airplane.equals("show"); - mCallbackHandler.setIsAirplaneMode(new IconState(show, - TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, - mContext)); - } - String fully = args.getString("fully"); - if (fully != null) { - mDemoInetCondition = Boolean.parseBoolean(fully); - BitSet connected = new BitSet(); - if (mDemoInetCondition) { - connected.set(mWifiSignalController.mTransportType); - } - mWifiSignalController.updateConnectivity(connected, connected); - for (int i = 0; i < mMobileSignalControllers.size(); i++) { - MobileSignalController controller = mMobileSignalControllers.valueAt(i); - if (mDemoInetCondition) { - connected.set(controller.mTransportType); - } - controller.updateConnectivity(connected, connected); + connected.set(controller.mTransportType); } + controller.updateConnectivity(connected, connected); } - String wifi = args.getString("wifi"); - if (wifi != null) { - boolean show = wifi.equals("show"); - String level = args.getString("level"); - if (level != null) { - mDemoWifiState.level = level.equals("null") ? -1 - : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1); - mDemoWifiState.connected = mDemoWifiState.level >= 0; - } - String activity = args.getString("activity"); - if (activity != null) { - switch (activity) { - case "inout": - mWifiSignalController.setActivity(DATA_ACTIVITY_INOUT); - break; - case "in": - mWifiSignalController.setActivity(DATA_ACTIVITY_IN); - break; - case "out": - mWifiSignalController.setActivity(DATA_ACTIVITY_OUT); - break; - default: - mWifiSignalController.setActivity(DATA_ACTIVITY_NONE); - break; - } - } else { - mWifiSignalController.setActivity(DATA_ACTIVITY_NONE); - } - String ssid = args.getString("ssid"); - if (ssid != null) { - mDemoWifiState.ssid = ssid; - } - mDemoWifiState.enabled = show; - mWifiSignalController.notifyListeners(); + } + String wifi = args.getString("wifi"); + if (wifi != null) { + boolean show = wifi.equals("show"); + String level = args.getString("level"); + if (level != null) { + mDemoWifiState.level = level.equals("null") ? -1 + : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1); + mDemoWifiState.connected = mDemoWifiState.level >= 0; } - String sims = args.getString("sims"); - if (sims != null) { - int num = MathUtils.constrain(Integer.parseInt(sims), 1, 8); - List<SubscriptionInfo> subs = new ArrayList<>(); - if (num != mMobileSignalControllers.size()) { - mMobileSignalControllers.clear(); - int start = mSubscriptionManager.getActiveSubscriptionInfoCountMax(); - for (int i = start /* get out of normal index range */; i < start + num; i++) { - subs.add(addSignalController(i, i)); - } - mCallbackHandler.setSubs(subs); - for (int i = 0; i < mMobileSignalControllers.size(); i++) { - int key = mMobileSignalControllers.keyAt(i); - MobileSignalController controller = mMobileSignalControllers.get(key); - controller.notifyListeners(); - } + String activity = args.getString("activity"); + if (activity != null) { + switch (activity) { + case "inout": + mWifiSignalController.setActivity(DATA_ACTIVITY_INOUT); + break; + case "in": + mWifiSignalController.setActivity(DATA_ACTIVITY_IN); + break; + case "out": + mWifiSignalController.setActivity(DATA_ACTIVITY_OUT); + break; + default: + mWifiSignalController.setActivity(DATA_ACTIVITY_NONE); + break; } + } else { + mWifiSignalController.setActivity(DATA_ACTIVITY_NONE); } - String nosim = args.getString("nosim"); - if (nosim != null) { - mHasNoSubs = nosim.equals("show"); - mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected); + String ssid = args.getString("ssid"); + if (ssid != null) { + mDemoWifiState.ssid = ssid; } - String mobile = args.getString("mobile"); - if (mobile != null) { - boolean show = mobile.equals("show"); - String datatype = args.getString("datatype"); - String slotString = args.getString("slot"); - int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString); - slot = MathUtils.constrain(slot, 0, 8); - // Ensure we have enough sim slots - List<SubscriptionInfo> subs = new ArrayList<>(); - while (mMobileSignalControllers.size() <= slot) { - int nextSlot = mMobileSignalControllers.size(); - subs.add(addSignalController(nextSlot, nextSlot)); - } - if (!subs.isEmpty()) { - mCallbackHandler.setSubs(subs); - } - // Hack to index linearly for easy use. - MobileSignalController controller = mMobileSignalControllers.valueAt(slot); - controller.getState().dataSim = datatype != null; - controller.getState().isDefault = datatype != null; - controller.getState().dataConnected = datatype != null; - if (datatype != null) { - controller.getState().iconGroup = - datatype.equals("1x") ? TelephonyIcons.ONE_X : - datatype.equals("3g") ? TelephonyIcons.THREE_G : - datatype.equals("4g") ? TelephonyIcons.FOUR_G : - datatype.equals("4g+") ? TelephonyIcons.FOUR_G_PLUS : - datatype.equals("5g") ? TelephonyIcons.NR_5G : - datatype.equals("5ge") ? TelephonyIcons.LTE_CA_5G_E : - datatype.equals("5g+") ? TelephonyIcons.NR_5G_PLUS : - datatype.equals("e") ? TelephonyIcons.E : - datatype.equals("g") ? TelephonyIcons.G : - datatype.equals("h") ? TelephonyIcons.H : - datatype.equals("h+") ? TelephonyIcons.H_PLUS : - datatype.equals("lte") ? TelephonyIcons.LTE : - datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS : - datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED : - datatype.equals("not") ? TelephonyIcons.NOT_DEFAULT_DATA : - TelephonyIcons.UNKNOWN; - } - if (args.containsKey("roam")) { - controller.getState().roaming = "show".equals(args.getString("roam")); - } - String level = args.getString("level"); - if (level != null) { - controller.getState().level = level.equals("null") ? -1 - : Math.min(Integer.parseInt(level), - CellSignalStrength.getNumSignalStrengthLevels()); - controller.getState().connected = controller.getState().level >= 0; - } - if (args.containsKey("inflate")) { - for (int i = 0; i < mMobileSignalControllers.size(); i++) { - mMobileSignalControllers.valueAt(i).mInflateSignalStrengths = - "true".equals(args.getString("inflate")); - } + mDemoWifiState.enabled = show; + mWifiSignalController.notifyListeners(); + } + String sims = args.getString("sims"); + if (sims != null) { + int num = MathUtils.constrain(Integer.parseInt(sims), 1, 8); + List<SubscriptionInfo> subs = new ArrayList<>(); + if (num != mMobileSignalControllers.size()) { + mMobileSignalControllers.clear(); + int start = mSubscriptionManager.getActiveSubscriptionInfoCountMax(); + for (int i = start /* get out of normal index range */; i < start + num; i++) { + subs.add(addSignalController(i, i)); } - String activity = args.getString("activity"); - if (activity != null) { - controller.getState().dataConnected = true; - switch (activity) { - case "inout": - controller.setActivity(TelephonyManager.DATA_ACTIVITY_INOUT); - break; - case "in": - controller.setActivity(TelephonyManager.DATA_ACTIVITY_IN); - break; - case "out": - controller.setActivity(TelephonyManager.DATA_ACTIVITY_OUT); - break; - default: - controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE); - break; - } - } else { - controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE); + mCallbackHandler.setSubs(subs); + for (int i = 0; i < mMobileSignalControllers.size(); i++) { + int key = mMobileSignalControllers.keyAt(i); + MobileSignalController controller = mMobileSignalControllers.get(key); + controller.notifyListeners(); } - controller.getState().enabled = show; - controller.notifyListeners(); } - String carrierNetworkChange = args.getString("carriernetworkchange"); - if (carrierNetworkChange != null) { - boolean show = carrierNetworkChange.equals("show"); + } + String nosim = args.getString("nosim"); + if (nosim != null) { + mHasNoSubs = nosim.equals("show"); + mCallbackHandler.setNoSims(mHasNoSubs, mSimDetected); + } + String mobile = args.getString("mobile"); + if (mobile != null) { + boolean show = mobile.equals("show"); + String datatype = args.getString("datatype"); + String slotString = args.getString("slot"); + int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString); + slot = MathUtils.constrain(slot, 0, 8); + // Ensure we have enough sim slots + List<SubscriptionInfo> subs = new ArrayList<>(); + while (mMobileSignalControllers.size() <= slot) { + int nextSlot = mMobileSignalControllers.size(); + subs.add(addSignalController(nextSlot, nextSlot)); + } + if (!subs.isEmpty()) { + mCallbackHandler.setSubs(subs); + } + // Hack to index linearly for easy use. + MobileSignalController controller = mMobileSignalControllers.valueAt(slot); + controller.getState().dataSim = datatype != null; + controller.getState().isDefault = datatype != null; + controller.getState().dataConnected = datatype != null; + if (datatype != null) { + controller.getState().iconGroup = + datatype.equals("1x") ? TelephonyIcons.ONE_X : + datatype.equals("3g") ? TelephonyIcons.THREE_G : + datatype.equals("4g") ? TelephonyIcons.FOUR_G : + datatype.equals("4g+") ? TelephonyIcons.FOUR_G_PLUS : + datatype.equals("5g") ? TelephonyIcons.NR_5G : + datatype.equals("5ge") ? TelephonyIcons.LTE_CA_5G_E : + datatype.equals("5g+") ? TelephonyIcons.NR_5G_PLUS : + datatype.equals("e") ? TelephonyIcons.E : + datatype.equals("g") ? TelephonyIcons.G : + datatype.equals("h") ? TelephonyIcons.H : + datatype.equals("h+") ? TelephonyIcons.H_PLUS : + datatype.equals("lte") ? TelephonyIcons.LTE : + datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS : + datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED : + datatype.equals("not") ? TelephonyIcons.NOT_DEFAULT_DATA : + TelephonyIcons.UNKNOWN; + } + if (args.containsKey("roam")) { + controller.getState().roaming = "show".equals(args.getString("roam")); + } + String level = args.getString("level"); + if (level != null) { + controller.getState().level = level.equals("null") ? -1 + : Math.min(Integer.parseInt(level), + CellSignalStrength.getNumSignalStrengthLevels()); + controller.getState().connected = controller.getState().level >= 0; + } + if (args.containsKey("inflate")) { for (int i = 0; i < mMobileSignalControllers.size(); i++) { - MobileSignalController controller = mMobileSignalControllers.valueAt(i); - controller.setCarrierNetworkChangeMode(show); + mMobileSignalControllers.valueAt(i).mInflateSignalStrengths = + "true".equals(args.getString("inflate")); } } + String activity = args.getString("activity"); + if (activity != null) { + controller.getState().dataConnected = true; + switch (activity) { + case "inout": + controller.setActivity(TelephonyManager.DATA_ACTIVITY_INOUT); + break; + case "in": + controller.setActivity(TelephonyManager.DATA_ACTIVITY_IN); + break; + case "out": + controller.setActivity(TelephonyManager.DATA_ACTIVITY_OUT); + break; + default: + controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE); + break; + } + } else { + controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE); + } + controller.getState().enabled = show; + controller.notifyListeners(); + } + String carrierNetworkChange = args.getString("carriernetworkchange"); + if (carrierNetworkChange != null) { + boolean show = carrierNetworkChange.equals("show"); + for (int i = 0; i < mMobileSignalControllers.size(); i++) { + MobileSignalController controller = mMobileSignalControllers.valueAt(i); + controller.setCarrierNetworkChangeMode(show); + } } } + @Override + public List<String> demoCommands() { + List<String> s = new ArrayList<>(); + s.add(DemoMode.COMMAND_NETWORK); + return s; + } + private SubscriptionInfo addSignalController(int id, int simSlotIndex) { SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0, null, null, null, "", false, null, null); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java index 288b3aff2af6..272c494b1af4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java @@ -23,17 +23,20 @@ import android.content.Intent; import android.content.IntentFilter; import android.os.UserHandle; +import androidx.annotation.NonNull; + +import com.android.systemui.dagger.SysUISingleton; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import javax.inject.Inject; -import javax.inject.Singleton; /** * Implementation of {@link NextAlarmController} */ -@Singleton +@SysUISingleton public class NextAlarmControllerImpl extends BroadcastReceiver implements NextAlarmController { @@ -59,12 +62,14 @@ public class NextAlarmControllerImpl extends BroadcastReceiver pw.print(" mNextAlarm="); pw.println(mNextAlarm); } - public void addCallback(NextAlarmChangeCallback cb) { + @Override + public void addCallback(@NonNull NextAlarmChangeCallback cb) { mChangeCallbacks.add(cb); cb.onNextAlarmChanged(mNextAlarm); } - public void removeCallback(NextAlarmChangeCallback cb) { + @Override + public void removeCallback(@NonNull NextAlarmChangeCallback cb) { mChangeCallbacks.remove(cb); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java index 7ef9945b4d0e..ac8b47dc7e0b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java @@ -21,17 +21,17 @@ import android.content.Context; import android.content.res.Configuration; import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.qs.QSFragment; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.StatusBar; import javax.inject.Inject; -import javax.inject.Singleton; /** * Let {@link RemoteInputView} to control the visibility of QuickSetting. */ -@Singleton +@SysUISingleton public class RemoteInputQuickSettingsDisabler implements ConfigurationController.ConfigurationListener { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputUriController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputUriController.java index b5031832adc5..03b6122102c2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputUriController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputUriController.java @@ -23,17 +23,17 @@ import android.util.Log; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import javax.inject.Inject; -import javax.inject.Singleton; /** * Handles granting and revoking inline URI grants associated with RemoteInputs. */ -@Singleton +@SysUISingleton public class RemoteInputUriController { private final IStatusBarService mStatusBarManagerService; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java index 1f368e164678..53d68d0ff0ac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java @@ -19,15 +19,17 @@ package com.android.systemui.statusbar.policy; import android.content.Context; import android.os.UserHandle; +import androidx.annotation.NonNull; + import com.android.internal.view.RotationPolicy; +import com.android.systemui.dagger.SysUISingleton; import java.util.concurrent.CopyOnWriteArrayList; import javax.inject.Inject; -import javax.inject.Singleton; /** Platform implementation of the rotation lock controller. **/ -@Singleton +@SysUISingleton public final class RotationLockControllerImpl implements RotationLockController { private final Context mContext; private final CopyOnWriteArrayList<RotationLockControllerCallback> mCallbacks = @@ -47,12 +49,14 @@ public final class RotationLockControllerImpl implements RotationLockController setListening(true); } - public void addCallback(RotationLockControllerCallback callback) { + @Override + public void addCallback(@NonNull RotationLockControllerCallback callback) { mCallbacks.add(callback); notifyChanged(callback); } - public void removeCallback(RotationLockControllerCallback callback) { + @Override + public void removeCallback(@NonNull RotationLockControllerCallback callback) { mCallbacks.remove(callback); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java index 309d4b04ebbf..7e54e8d1c1c3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java @@ -42,11 +42,14 @@ import android.util.Log; import android.util.Pair; import android.util.SparseArray; +import androidx.annotation.NonNull; + import com.android.internal.annotations.GuardedBy; import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.VpnConfig; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.settings.CurrentUserTracker; @@ -56,11 +59,10 @@ import java.util.ArrayList; import java.util.concurrent.Executor; import javax.inject.Inject; -import javax.inject.Singleton; /** */ -@Singleton +@SysUISingleton public class SecurityControllerImpl extends CurrentUserTracker implements SecurityController { private static final String TAG = "SecurityController"; @@ -274,7 +276,7 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi } @Override - public void removeCallback(SecurityControllerCallback callback) { + public void removeCallback(@NonNull SecurityControllerCallback callback) { synchronized (mCallbacks) { if (callback == null) return; if (DEBUG) Log.d(TAG, "removeCallback " + callback); @@ -283,7 +285,7 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi } @Override - public void addCallback(SecurityControllerCallback callback) { + public void addCallback(@NonNull SecurityControllerCallback callback) { synchronized (mCallbacks) { if (callback == null || mCallbacks.contains(callback)) return; if (DEBUG) Log.d(TAG, "addCallback " + callback); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java index 5db66932d3c1..20cc46ff6bbd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java @@ -19,16 +19,19 @@ package com.android.systemui.statusbar.policy; import android.content.Context; import android.hardware.SensorPrivacyManager; +import androidx.annotation.NonNull; + +import com.android.systemui.dagger.SysUISingleton; + import java.util.ArrayList; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controls sensor privacy state and notification. */ -@Singleton +@SysUISingleton public class SensorPrivacyControllerImpl implements SensorPrivacyController, SensorPrivacyManager.OnSensorPrivacyChangedListener { private SensorPrivacyManager mSensorPrivacyManager; @@ -60,7 +63,7 @@ public class SensorPrivacyControllerImpl implements SensorPrivacyController, /** * Adds the provided listener for callbacks when sensor privacy state changes. */ - public void addCallback(OnSensorPrivacyChangedListener listener) { + public void addCallback(@NonNull OnSensorPrivacyChangedListener listener) { synchronized (mLock) { mListeners.add(listener); notifyListenerLocked(listener); @@ -70,7 +73,7 @@ public class SensorPrivacyControllerImpl implements SensorPrivacyController, /** * Removes the provided listener from callbacks when sensor privacy state changes. */ - public void removeCallback(OnSensorPrivacyChangedListener listener) { + public void removeCallback(@NonNull OnSensorPrivacyChangedListener listener) { synchronized (mLock) { mListeners.remove(listener); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java index 311e873812ac..52a6bcaa6753 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java @@ -27,13 +27,13 @@ import android.util.Log; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.util.DeviceConfigProxy; import javax.inject.Inject; -import javax.inject.Singleton; -@Singleton +@SysUISingleton public final class SmartReplyConstants { private static final String TAG = "SmartReplyConstants"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java index 0ca6ff6ec66e..9eaee22b54ec 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java @@ -34,18 +34,20 @@ import android.os.UserManager; import android.provider.ContactsContract; import android.util.Log; +import androidx.annotation.NonNull; + import com.android.internal.util.UserIcons; import com.android.settingslib.drawable.UserIconDrawable; import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; import java.util.ArrayList; import javax.inject.Inject; -import javax.inject.Singleton; /** */ -@Singleton +@SysUISingleton public class UserInfoControllerImpl implements UserInfoController { private static final String TAG = "UserInfoController"; @@ -75,12 +77,14 @@ public class UserInfoControllerImpl implements UserInfoController { null, null); } - public void addCallback(OnUserInfoChangedListener callback) { + @Override + public void addCallback(@NonNull OnUserInfoChangedListener callback) { mCallbacks.add(callback); callback.onUserInfoChanged(mUserName, mUserDrawable, mUserAccount); } - public void removeCallback(OnUserInfoChangedListener callback) { + @Override + public void removeCallback(@NonNull OnUserInfoChangedListener callback) { mCallbacks.remove(callback); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index ce5bb0508c0a..f9ac760a3367 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -62,6 +62,7 @@ import com.android.systemui.Prefs.Key; import com.android.systemui.R; import com.android.systemui.SystemUISecondaryUserService; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.DetailAdapter; @@ -76,12 +77,11 @@ import java.util.ArrayList; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * Keeps a list of all users on the device for user switching. */ -@Singleton +@SysUISingleton public class UserSwitcherController implements Dumpable { public static final float USER_SWITCH_ENABLED_ALPHA = 1.0f; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java index 5257ce4c6bd9..4ae96651b570 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java @@ -84,7 +84,7 @@ public class WifiSignalController extends R.bool.config_showWifiIndicatorWhenEnabled); boolean wifiVisible = mCurrentState.enabled && ( (mCurrentState.connected && mCurrentState.inetCondition == 1) - || !mHasMobileDataFeature || mWifiTracker.isDefaultNetwork + || !mHasMobileDataFeature || mCurrentState.isDefault || visibleWhenEnabled); String wifiDesc = mCurrentState.connected ? mCurrentState.ssid : null; boolean ssidPresent = wifiVisible && mCurrentState.ssid != null; @@ -107,6 +107,7 @@ public class WifiSignalController extends public void fetchInitialState() { mWifiTracker.fetchInitialState(); mCurrentState.enabled = mWifiTracker.enabled; + mCurrentState.isDefault = mWifiTracker.isDefaultNetwork; mCurrentState.connected = mWifiTracker.connected; mCurrentState.ssid = mWifiTracker.ssid; mCurrentState.rssi = mWifiTracker.rssi; @@ -121,6 +122,7 @@ public class WifiSignalController extends public void handleBroadcast(Intent intent) { mWifiTracker.handleBroadcast(intent); mCurrentState.enabled = mWifiTracker.enabled; + mCurrentState.isDefault = mWifiTracker.isDefaultNetwork; mCurrentState.connected = mWifiTracker.connected; mCurrentState.ssid = mWifiTracker.ssid; mCurrentState.rssi = mWifiTracker.rssi; @@ -131,6 +133,7 @@ public class WifiSignalController extends private void handleStatusUpdated() { mCurrentState.statusLabel = mWifiTracker.statusLabel; + mCurrentState.isDefault = mWifiTracker.isDefaultNetwork; notifyListenersIfNecessary(); } @@ -156,6 +159,7 @@ public class WifiSignalController extends static class WifiState extends SignalController.State { String ssid; boolean isTransient; + boolean isDefault; String statusLabel; @Override @@ -164,6 +168,7 @@ public class WifiSignalController extends WifiState state = (WifiState) s; ssid = state.ssid; isTransient = state.isTransient; + isDefault = state.isDefault; statusLabel = state.statusLabel; } @@ -172,6 +177,7 @@ public class WifiSignalController extends super.toString(builder); builder.append(",ssid=").append(ssid) .append(",isTransient=").append(isTransient) + .append(",isDefault=").append(isDefault) .append(",statusLabel=").append(statusLabel); } @@ -183,6 +189,7 @@ public class WifiSignalController extends WifiState other = (WifiState) o; return Objects.equals(other.ssid, ssid) && other.isTransient == isTransient + && other.isDefault == isDefault && TextUtils.equals(other.statusLabel, statusLabel); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java index 4376a0145826..897a3b863e73 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java @@ -37,9 +37,12 @@ import android.service.notification.ZenModeConfig.ZenRule; import android.text.format.DateFormat; import android.util.Log; +import androidx.annotation.NonNull; + import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Dumpable; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.qs.GlobalSetting; import com.android.systemui.settings.CurrentUserTracker; @@ -51,10 +54,9 @@ import java.util.ArrayList; import java.util.Objects; import javax.inject.Inject; -import javax.inject.Singleton; /** Platform implementation of the zen mode controller. **/ -@Singleton +@SysUISingleton public class ZenModeControllerImpl extends CurrentUserTracker implements ZenModeController, Dumpable { private static final String TAG = "ZenModeController"; @@ -124,14 +126,14 @@ public class ZenModeControllerImpl extends CurrentUserTracker } @Override - public void addCallback(Callback callback) { + public void addCallback(@NonNull Callback callback) { synchronized (mCallbacksLock) { mCallbacks.add(callback); } } @Override - public void removeCallback(Callback callback) { + public void removeCallback(@NonNull Callback callback) { synchronized (mCallbacksLock) { mCallbacks.remove(callback); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java index c0602762ef29..bcfff60dadf3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java @@ -29,11 +29,11 @@ import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.R; import com.android.systemui.SystemUI; import com.android.systemui.assist.AssistManager; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.tv.micdisclosure.AudioRecordingDisclosureBar; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; @@ -46,7 +46,7 @@ import dagger.Lazy; * recording, discloses the responsible applications </li> * </ul> */ -@Singleton +@SysUISingleton public class TvStatusBar extends SystemUI implements CommandQueue.Callbacks { private static final String ACTION_OPEN_TV_NOTIFICATIONS_PANEL = diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java index dde8854a2b35..a29db4d98329 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java @@ -26,8 +26,6 @@ import android.animation.ObjectAnimator; import android.annotation.IntDef; import android.annotation.UiThread; import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; import android.graphics.PixelFormat; import android.provider.DeviceConfig; import android.text.TextUtils; @@ -47,9 +45,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.Collections; -import java.util.LinkedList; import java.util.List; -import java.util.Queue; import java.util.Set; /** @@ -77,9 +73,6 @@ public class AudioRecordingDisclosureBar implements STATE_NOT_SHOWN, STATE_APPEARING, STATE_SHOWN, - STATE_MINIMIZING, - STATE_MINIMIZED, - STATE_MAXIMIZING, STATE_DISAPPEARING }) public @interface State {} @@ -88,13 +81,9 @@ public class AudioRecordingDisclosureBar implements private static final int STATE_NOT_SHOWN = 0; private static final int STATE_APPEARING = 1; private static final int STATE_SHOWN = 2; - private static final int STATE_MINIMIZING = 3; - private static final int STATE_MINIMIZED = 4; - private static final int STATE_MAXIMIZING = 5; - private static final int STATE_DISAPPEARING = 6; + private static final int STATE_DISAPPEARING = 3; private static final int ANIMATION_DURATION = 600; - private static final int MAXIMIZED_DURATION = 3000; private final Context mContext; private boolean mIsEnabled; @@ -116,30 +105,6 @@ public class AudioRecordingDisclosureBar implements */ private AudioActivityObserver[] mAudioActivityObservers; /** - * Whether the indicator should expand and show the recording application's label. - * If disabled ({@code false}) the "minimized" ({@link #STATE_MINIMIZED}) indicator would appear - * on the screen whenever an application is recording, but will not reveal to the user what - * application this is. - */ - private final boolean mRevealRecordingPackages; - /** - * Set of applications that we've notified the user about since the indicator came up. Meaning - * that if an application is in this list then at some point since the indicator came up, it - * was expanded showing this application's title. - * Used not to notify the user about the same application again while the indicator is shown. - * We empty this set every time the indicator goes off the screen (we always call {@code - * mSessionNotifiedPackages.clear()} before calling {@link #hide()}). - */ - private final Set<String> mSessionNotifiedPackages = new ArraySet<>(); - /** - * If an application starts recording while the TV indicator is neither in {@link - * #STATE_NOT_SHOWN} nor in {@link #STATE_MINIMIZED}, then we add the application's package - * name to the queue, from which we take packages names one by one to disclose the - * corresponding applications' titles to the user, whenever the indicator eventually comes to - * one of the two aforementioned states. - */ - private final Queue<String> mPendingNotificationPackages = new LinkedList<>(); - /** * Set of applications for which we make an exception and do not show the indicator. This gets * populated once - in {@link #AudioRecordingDisclosureBar(Context)}. */ @@ -149,8 +114,6 @@ public class AudioRecordingDisclosureBar implements mContext = context; // Load configs - mRevealRecordingPackages = mContext.getResources().getBoolean( - R.bool.audio_recording_disclosure_reveal_packages); reloadExemptPackages(); mIsEnabled = DeviceConfig.getBoolean(NAMESPACE_PRIVACY, ENABLED_FLAG, true); @@ -210,10 +173,6 @@ public class AudioRecordingDisclosureBar implements if (mState != STATE_NOT_SHOWN) { removeIndicatorView(); } - - // Clean up the state. - mSessionNotifiedPackages.clear(); - mPendingNotificationPackages.clear(); } @UiThread @@ -231,68 +190,29 @@ public class AudioRecordingDisclosureBar implements } if (active) { - showIndicatorForPackageIfNeeded(packageName); + showIfNotShown(); } else { hideIndicatorIfNeeded(); } } @UiThread - private void showIndicatorForPackageIfNeeded(String packageName) { - if (DEBUG) Log.d(TAG, "showIndicatorForPackageIfNeeded, packageName=" + packageName); - if (!mSessionNotifiedPackages.add(packageName)) { - // We've already notified user about this app, no need to do it again. - if (DEBUG) Log.d(TAG, " - already notified"); - return; - } - - switch (mState) { - case STATE_NOT_SHOWN: - show(packageName); - break; - - case STATE_MINIMIZED: - if (mRevealRecordingPackages) { - expand(packageName); - } - break; - - case STATE_DISAPPEARING: - case STATE_APPEARING: - case STATE_MAXIMIZING: - case STATE_SHOWN: - case STATE_MINIMIZING: - // Currently animating or expanded. Thus add to the pending notifications, and it - // will be picked up once the indicator comes to the STATE_MINIMIZED. - mPendingNotificationPackages.add(packageName); - break; - } - } - - @UiThread private void hideIndicatorIfNeeded() { - // If not MINIMIZED, will check whether the indicator should be hidden when the indicator - // comes to the STATE_MINIMIZED eventually. - if (mState != STATE_MINIMIZED) return; - - // If is in the STATE_MINIMIZED, but there are other active recorders - simply ignore. - for (int index = mAudioActivityObservers.length - 1; index >= 0; index--) { - for (String activePackage : mAudioActivityObservers[index].getActivePackages()) { - if (mExemptPackages.contains(activePackage)) continue; - return; - } + // If not STATE_APPEARING, will check whether the indicator should be hidden when the + // indicator comes to the STATE_SHOWN. + // If STATE_DISAPPEARING or STATE_SHOWN - nothing else for us to do here. + if (mState != STATE_SHOWN) return; + + // If is in the STATE_SHOWN and there are no active recorders - hide. + if (!hasActiveRecorders()) { + hide(); } - - // Clear the state and hide the indicator. - mSessionNotifiedPackages.clear(); - hide(); } @UiThread - private void show(String packageName) { - if (DEBUG) { - Log.d(TAG, "Showing indicator"); - } + private void showIfNotShown() { + if (mState != STATE_NOT_SHOWN) return; + if (DEBUG) Log.d(TAG, "Showing indicator"); mIsLtr = mContext.getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_LTR; @@ -308,30 +228,14 @@ public class AudioRecordingDisclosureBar implements mTextView = mTextsContainers.findViewById(R.id.text); mBgEnd = mIndicatorView.findViewById(R.id.bg_end); - // Set up the notification text - if (mRevealRecordingPackages) { - // Swap background drawables depending on layout directions (both drawables have rounded - // corners only on one side) - if (mIsLtr) { - mBgEnd.setBackgroundResource(R.drawable.tv_rect_dark_right_rounded); - mIconContainerBg.setBackgroundResource(R.drawable.tv_rect_dark_left_rounded); - } else { - mBgEnd.setBackgroundResource(R.drawable.tv_rect_dark_left_rounded); - mIconContainerBg.setBackgroundResource(R.drawable.tv_rect_dark_right_rounded); - } - - final String label = getApplicationLabel(packageName); - mTextView.setText(mContext.getString(R.string.app_accessed_mic, label)); - } else { - mTextsContainers.setVisibility(View.GONE); - mIconContainerBg.setVisibility(View.GONE); - mTextView.setVisibility(View.GONE); - mBgEnd.setVisibility(View.GONE); - mTextsContainers = null; - mIconContainerBg = null; - mTextView = null; - mBgEnd = null; - } + mTextsContainers.setVisibility(View.GONE); + mIconContainerBg.setVisibility(View.GONE); + mTextView.setVisibility(View.GONE); + mBgEnd.setVisibility(View.GONE); + mTextsContainers = null; + mIconContainerBg = null; + mTextView = null; + mBgEnd = null; // Initially change the visibility to INVISIBLE, wait until and receives the size and // then animate it moving from "off" the screen correctly @@ -366,9 +270,7 @@ public class AudioRecordingDisclosureBar implements @Override public void onAnimationStart(Animator animation, boolean isReverse) { - if (mState == STATE_STOPPED) { - return; - } + if (mState == STATE_STOPPED) return; // Indicator is INVISIBLE at the moment, change it. mIndicatorView.setVisibility(View.VISIBLE); @@ -376,11 +278,7 @@ public class AudioRecordingDisclosureBar implements @Override public void onAnimationEnd(Animator animation) { - if (mRevealRecordingPackages) { - onExpanded(); - } else { - onMinimized(); - } + onAppeared(); } }); set.start(); @@ -404,60 +302,9 @@ public class AudioRecordingDisclosureBar implements } @UiThread - private void expand(String packageName) { - assertRevealingRecordingPackages(); - - final String label = getApplicationLabel(packageName); - mTextView.setText(mContext.getString(R.string.app_accessed_mic, label)); - - final AnimatorSet set = new AnimatorSet(); - set.playTogether( - ObjectAnimator.ofFloat(mIconTextsContainer, View.TRANSLATION_X, 0), - ObjectAnimator.ofFloat(mIconContainerBg, View.ALPHA, 1f), - ObjectAnimator.ofFloat(mTextsContainers, View.ALPHA, 1f), - ObjectAnimator.ofFloat(mBgEnd, View.ALPHA, 1f)); - set.setDuration(ANIMATION_DURATION); - set.addListener( - new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - onExpanded(); - } - }); - set.start(); - - mState = STATE_MAXIMIZING; - } - - @UiThread - private void minimize() { - assertRevealingRecordingPackages(); - - final int targetOffset = (mIsLtr ? 1 : -1) * mTextsContainers.getWidth(); - final AnimatorSet set = new AnimatorSet(); - set.playTogether( - ObjectAnimator.ofFloat(mIconTextsContainer, View.TRANSLATION_X, targetOffset), - ObjectAnimator.ofFloat(mIconContainerBg, View.ALPHA, 0f), - ObjectAnimator.ofFloat(mTextsContainers, View.ALPHA, 0f), - ObjectAnimator.ofFloat(mBgEnd, View.ALPHA, 0f)); - set.setDuration(ANIMATION_DURATION); - set.addListener( - new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - onMinimized(); - } - }); - set.start(); - - mState = STATE_MINIMIZING; - } - - @UiThread private void hide() { - if (DEBUG) { - Log.d(TAG, "Hide indicator"); - } + if (DEBUG) Log.d(TAG, "Hide indicator"); + final int targetOffset = (mIsLtr ? 1 : -1) * (mIndicatorView.getWidth() - (int) mIconTextsContainer.getTranslationX()); final AnimatorSet set = new AnimatorSet(); @@ -477,51 +324,37 @@ public class AudioRecordingDisclosureBar implements mState = STATE_DISAPPEARING; } - @UiThread - private void onExpanded() { - if (mState == STATE_STOPPED) { - return; - } - - assertRevealingRecordingPackages(); - - mState = STATE_SHOWN; - - mIndicatorView.postDelayed(this::minimize, MAXIMIZED_DURATION); - } @UiThread - private void onMinimized() { - if (mState == STATE_STOPPED) { - return; - } + private void onAppeared() { + if (mState == STATE_STOPPED) return; - mState = STATE_MINIMIZED; + mState = STATE_SHOWN; - if (mRevealRecordingPackages) { - if (!mPendingNotificationPackages.isEmpty()) { - // There is a new application that started recording, tell the user about it. - expand(mPendingNotificationPackages.poll()); - } else { - hideIndicatorIfNeeded(); - } - } + hideIndicatorIfNeeded(); } @UiThread private void onHidden() { - if (mState == STATE_STOPPED) { - return; - } + if (mState == STATE_STOPPED) return; removeIndicatorView(); mState = STATE_NOT_SHOWN; - // Check if anybody started recording while we were in STATE_DISAPPEARING - if (!mPendingNotificationPackages.isEmpty()) { - // There is a new application that started recording, tell the user about it. - show(mPendingNotificationPackages.poll()); + if (hasActiveRecorders()) { + // Got new recorders, show again. + showIfNotShown(); + } + } + + private boolean hasActiveRecorders() { + for (int index = mAudioActivityObservers.length - 1; index >= 0; index--) { + for (String activePackage : mAudioActivityObservers[index].getActivePackages()) { + if (mExemptPackages.contains(activePackage)) continue; + return true; + } } + return false; } private void removeIndicatorView() { @@ -538,26 +371,6 @@ public class AudioRecordingDisclosureBar implements mBgEnd = null; } - private String getApplicationLabel(String packageName) { - assertRevealingRecordingPackages(); - - final PackageManager pm = mContext.getPackageManager(); - final ApplicationInfo appInfo; - try { - appInfo = pm.getApplicationInfo(packageName, 0); - } catch (PackageManager.NameNotFoundException e) { - return packageName; - } - return pm.getApplicationLabel(appInfo).toString(); - } - - private void assertRevealingRecordingPackages() { - if (!mRevealRecordingPackages) { - Log.e(TAG, "Not revealing recording packages", - DEBUG ? new RuntimeException("Should not be called") : null); - } - } - private static List<String> splitByComma(String string) { return TextUtils.isEmpty(string) ? Collections.emptyList() : Arrays.asList( string.split(",")); diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java index f31f8eb0b20d..132e092b8ada 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java @@ -36,6 +36,7 @@ import android.util.Log; import com.android.systemui.R; import com.android.systemui.SystemUI; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.google.android.collect.Sets; @@ -48,7 +49,6 @@ import java.util.Map; import java.util.Set; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controls the application of theme overlays across the system for all users. @@ -59,7 +59,7 @@ import javax.inject.Singleton; * - Observing work profile changes and applying overlays from the primary user to their * associated work profiles */ -@Singleton +@SysUISingleton public class ThemeOverlayController extends SystemUI { private static final String TAG = "ThemeOverlayController"; private static final boolean DEBUG = false; diff --git a/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java b/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java index 9b465ae15478..a2203732c47c 100644 --- a/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java +++ b/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java @@ -33,17 +33,17 @@ import android.widget.ToastPresenter; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.SystemUI; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.CommandQueue; import java.util.Objects; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controls display of text toasts. */ -@Singleton +@SysUISingleton public class ToastUI extends SystemUI implements CommandQueue.Callbacks { private static final String TAG = "ToastUI"; diff --git a/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java b/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java index 25ae09840600..8a8f92b32bfe 100644 --- a/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java +++ b/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java @@ -25,6 +25,7 @@ import android.os.SystemClock; import androidx.annotation.NonNull; import com.android.systemui.Dumpable; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; import com.android.systemui.shared.tracing.FrameProtoTracer; import com.android.systemui.shared.tracing.FrameProtoTracer.ProtoTraceParams; @@ -42,12 +43,11 @@ import java.util.ArrayList; import java.util.Queue; import javax.inject.Inject; -import javax.inject.Singleton; /** * Controller for coordinating winscope proto tracing. */ -@Singleton +@SysUISingleton public class ProtoTracer implements Dumpable, ProtoTraceParams<MessageNano, SystemUiTraceFileProto, SystemUiTraceEntryProto, SystemUiTraceProto> { diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java index 49ada1a5e41e..1f444340653d 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java @@ -15,14 +15,10 @@ */ package com.android.systemui.tuner; -import android.content.ContentResolver; +import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; -import android.database.ContentObserver; import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.provider.Settings; import android.view.MenuItem; import androidx.preference.Preference; @@ -33,13 +29,13 @@ import androidx.preference.SwitchPreference; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.systemui.DemoMode; import com.android.systemui.R; +import com.android.systemui.demomode.DemoMode; +import com.android.systemui.demomode.DemoModeAvailabilityTracker; +import com.android.systemui.demomode.DemoModeController; public class DemoModeFragment extends PreferenceFragment implements OnPreferenceChangeListener { - private static final String DEMO_MODE_ON = "sysui_tuner_demo_on"; - private static final String[] STATUS_ICONS = { "volume", "bluetooth", @@ -57,6 +53,17 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference private SwitchPreference mEnabledSwitch; private SwitchPreference mOnSwitch; + private DemoModeController mDemoModeController; + private Tracker mDemoModeTracker; + + // We are the only ones who ever call this constructor, so don't worry about the warning + @SuppressLint("ValidFragment") + public DemoModeFragment(DemoModeController demoModeController) { + super(); + mDemoModeController = demoModeController; + } + + @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { Context context = getContext(); @@ -73,13 +80,11 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference screen.addPreference(mOnSwitch); setPreferenceScreen(screen); + mDemoModeTracker = new Tracker(context); + mDemoModeTracker.startTracking(); updateDemoModeEnabled(); updateDemoModeOn(); - ContentResolver contentResolver = getContext().getContentResolver(); - contentResolver.registerContentObserver(Settings.Global.getUriFor( - DemoMode.DEMO_MODE_ALLOWED), false, mDemoModeObserver); - contentResolver.registerContentObserver(Settings.Global.getUriFor(DEMO_MODE_ON), false, - mDemoModeObserver); + setHasOptionsMenu(true); } @@ -107,21 +112,17 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference @Override public void onDestroy() { - getContext().getContentResolver().unregisterContentObserver(mDemoModeObserver); + mDemoModeTracker.stopTracking(); super.onDestroy(); } private void updateDemoModeEnabled() { - boolean enabled = Settings.Global.getInt(getContext().getContentResolver(), - DemoMode.DEMO_MODE_ALLOWED, 0) != 0; - mEnabledSwitch.setChecked(enabled); - mOnSwitch.setEnabled(enabled); + mEnabledSwitch.setChecked(mDemoModeTracker.isDemoModeAvailable()); + mOnSwitch.setEnabled(mDemoModeTracker.isDemoModeAvailable()); } private void updateDemoModeOn() { - boolean enabled = Settings.Global.getInt(getContext().getContentResolver(), - DEMO_MODE_ON, 0) != 0; - mOnSwitch.setChecked(enabled); + mOnSwitch.setChecked(mDemoModeTracker.isInDemoMode()); } @Override @@ -134,7 +135,7 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference stopDemoMode(); } MetricsLogger.action(getContext(), MetricsEvent.TUNER_DEMO_MODE_ENABLED, enabled); - setGlobal(DemoMode.DEMO_MODE_ALLOWED, enabled ? 1 : 0); + mDemoModeController.requestSetDemoModeAllowed(enabled); } else if (preference == mOnSwitch) { MetricsLogger.action(getContext(), MetricsEvent.TUNER_DEMO_MODE_ON, enabled); if (enabled) { @@ -151,11 +152,11 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference private void startDemoMode() { Intent intent = new Intent(DemoMode.ACTION_DEMO); - intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_ENTER); - getContext().sendBroadcast(intent); + mDemoModeController.requestStartDemoMode(); intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_CLOCK); + //TODO: everything below should move to DemoModeController, or some `initialState` command String demoTime = "1010"; // 10:10, a classic choice of horologists try { String[] versionParts = android.os.Build.VERSION.RELEASE_OR_CODENAME.split("\\."); @@ -194,25 +195,31 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference intent.putExtra("visible", "false"); getContext().sendBroadcast(intent); - setGlobal(DEMO_MODE_ON, 1); } private void stopDemoMode() { - Intent intent = new Intent(DemoMode.ACTION_DEMO); - intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT); - getContext().sendBroadcast(intent); - setGlobal(DEMO_MODE_ON, 0); + mDemoModeController.requestFinishDemoMode(); } - private void setGlobal(String key, int value) { - Settings.Global.putInt(getContext().getContentResolver(), key, value); - } + private class Tracker extends DemoModeAvailabilityTracker { + Tracker(Context context) { + super(context); + } - private final ContentObserver mDemoModeObserver = - new ContentObserver(new Handler(Looper.getMainLooper())) { - public void onChange(boolean selfChange) { + @Override + public void onDemoModeAvailabilityChanged() { updateDemoModeEnabled(); updateDemoModeOn(); - }; + } + + @Override + public void onDemoModeStarted() { + updateDemoModeOn(); + } + + @Override + public void onDemoModeFinished() { + updateDemoModeOn(); + } }; } diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java b/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java index 8f3a8f6ec960..d54c07c87b40 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java @@ -19,10 +19,10 @@ import android.view.View; import android.view.WindowManager; import com.android.systemui.Dependency; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.tuner.TunerService.Tunable; import javax.inject.Inject; -import javax.inject.Singleton; /** * Version of Space that can be resized by a tunable setting. @@ -77,7 +77,7 @@ public class TunablePadding implements Tunable { /** * Exists for easy injecting in tests. */ - @Singleton + @SysUISingleton public static class TunablePaddingService { private final TunerService mTunerService; diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java index 453c2f7da71f..78341edefbb2 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java @@ -31,6 +31,7 @@ import androidx.preference.PreferenceScreen; import com.android.systemui.Dependency; import com.android.systemui.R; +import com.android.systemui.demomode.DemoModeController; import com.android.systemui.fragments.FragmentService; import javax.inject.Inject; @@ -41,9 +42,12 @@ public class TunerActivity extends Activity implements private static final String TAG_TUNER = "tuner"; + private final DemoModeController mDemoModeController; + @Inject - TunerActivity() { + TunerActivity(DemoModeController demoModeController) { super(); + mDemoModeController = demoModeController; } protected void onCreate(Bundle savedInstanceState) { @@ -61,7 +65,8 @@ public class TunerActivity extends Activity implements final String action = getIntent().getAction(); boolean showDemoMode = action != null && action.equals( "com.android.settings.action.DEMO_MODE"); - final PreferenceFragment fragment = showDemoMode ? new DemoModeFragment() + final PreferenceFragment fragment = showDemoMode + ? new DemoModeFragment(mDemoModeController) : new TunerFragment(); getFragmentManager().beginTransaction().replace(R.id.content_frame, fragment, TAG_TUNER).commit(); diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java index 3af11ab43001..d9727a73f651 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java @@ -18,7 +18,6 @@ package com.android.systemui.tuner; import android.app.ActivityManager; import android.content.ContentResolver; import android.content.Context; -import android.content.Intent; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.net.Uri; @@ -33,9 +32,10 @@ import android.util.ArraySet; import com.android.internal.util.ArrayUtils; import com.android.systemui.DejankUtils; -import com.android.systemui.DemoMode; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.demomode.DemoModeController; import com.android.systemui.qs.QSTileHost; import com.android.systemui.settings.CurrentUserTracker; import com.android.systemui.statusbar.phone.StatusBarIconController; @@ -46,14 +46,14 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import javax.inject.Inject; -import javax.inject.Singleton; /** */ -@Singleton +@SysUISingleton public class TunerServiceImpl extends TunerService { + private static final String TAG = "TunerService"; private static final String TUNER_VERSION = "sysui_tuner_version"; private static final int CURRENT_TUNER_VERSION = 4; @@ -77,6 +77,7 @@ public class TunerServiceImpl extends TunerService { private final HashSet<Tunable> mTunables = LeakDetector.ENABLED ? new HashSet<>() : null; private final Context mContext; private final LeakDetector mLeakDetector; + private final DemoModeController mDemoModeController; private ContentResolver mContentResolver; private int mCurrentUser; @@ -85,11 +86,16 @@ public class TunerServiceImpl extends TunerService { /** */ @Inject - public TunerServiceImpl(Context context, @Main Handler mainHandler, - LeakDetector leakDetector, BroadcastDispatcher broadcastDispatcher) { + public TunerServiceImpl( + Context context, + @Main Handler mainHandler, + LeakDetector leakDetector, + DemoModeController demoModeController, + BroadcastDispatcher broadcastDispatcher) { mContext = context; mContentResolver = mContext.getContentResolver(); mLeakDetector = leakDetector; + mDemoModeController = demoModeController; for (UserInfo user : UserManager.get(mContext).getUsers()) { mCurrentUser = user.getUserHandle().getIdentifier(); @@ -245,12 +251,11 @@ public class TunerServiceImpl extends TunerService { } public void clearAllFromUser(int user) { - // A couple special cases. - Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null); - Intent intent = new Intent(DemoMode.ACTION_DEMO); - intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT); - mContext.sendBroadcast(intent); + // Turn off demo mode + mDemoModeController.requestFinishDemoMode(); + mDemoModeController.requestSetDemoModeAllowed(false); + // A couple special cases. for (String key : mTunableLookup.keySet()) { if (ArrayUtils.contains(RESET_EXCEPTION_LIST, key)) { continue; diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java index fd6ba1a6af0e..37aac1124048 100644 --- a/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java +++ b/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java @@ -16,14 +16,7 @@ package com.android.systemui.tv; -import com.android.systemui.dagger.DefaultComponentBinder; -import com.android.systemui.dagger.DependencyBinder; -import com.android.systemui.dagger.DependencyProvider; import com.android.systemui.dagger.GlobalRootComponent; -import com.android.systemui.dagger.SystemServicesModule; -import com.android.systemui.dagger.SystemUIBinder; -import com.android.systemui.dagger.SystemUIModule; -import com.android.systemui.onehanded.dagger.OneHandedModule; import javax.inject.Singleton; @@ -33,16 +26,7 @@ import dagger.Component; * Root component for Dagger injection. */ @Singleton -@Component(modules = { - DefaultComponentBinder.class, - DependencyProvider.class, - DependencyBinder.class, - OneHandedModule.class, - SystemServicesModule.class, - SystemUIBinder.class, - SystemUIModule.class, - TvSystemUIModule.class, - TvSystemUIBinder.class}) +@Component(modules = {TvSysUIComponentModule.class}) public interface TvGlobalRootComponent extends GlobalRootComponent { /** * Component Builder interface. This allows to bind Context instance in the component diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java index bc0cb51c64a3..b7bc8c8fb7c4 100644 --- a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java +++ b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java @@ -16,8 +16,15 @@ package com.android.systemui.tv; +import com.android.systemui.dagger.DefaultComponentBinder; +import com.android.systemui.dagger.DependencyBinder; +import com.android.systemui.dagger.DependencyProvider; import com.android.systemui.dagger.SysUIComponent; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.SystemServicesModule; +import com.android.systemui.dagger.SystemUIBinder; +import com.android.systemui.dagger.SystemUIModule; +import com.android.systemui.onehanded.dagger.OneHandedModule; import dagger.Subcomponent; @@ -25,7 +32,16 @@ import dagger.Subcomponent; * Dagger Subcomponent for Core SysUI. */ @SysUISingleton -@Subcomponent(modules = {}) +@Subcomponent(modules = { + DefaultComponentBinder.class, + DependencyProvider.class, + DependencyBinder.class, + OneHandedModule.class, + SystemServicesModule.class, + SystemUIBinder.class, + SystemUIModule.class, + TvSystemUIModule.class, + TvSystemUIBinder.class}) public interface TvSysUIComponent extends SysUIComponent { /** diff --git a/tests/AutoVerify/app3/src/com/android/test/autoverify/MainActivity.java b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponentModule.java index 09ef47212622..334bb013ae69 100644 --- a/tests/AutoVerify/app3/src/com/android/test/autoverify/MainActivity.java +++ b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponentModule.java @@ -13,3 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +package com.android.systemui.tv; + +import dagger.Module; + +/** + * Dagger module for including the WMComponent. + */ +@Module(subcomponents = {TvSysUIComponent.class}) +public abstract class TvSysUIComponentModule { +} diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java index 3f7350639fd3..ca9cb08c0a59 100644 --- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java @@ -27,8 +27,10 @@ import androidx.annotation.Nullable; import com.android.keyguard.KeyguardViewController; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dock.DockManager; import com.android.systemui.dock.DockManagerImpl; import com.android.systemui.doze.DozeHost; @@ -44,12 +46,14 @@ import com.android.systemui.stackdivider.DividerModule; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.phone.DozeServiceHost; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl; import com.android.systemui.statusbar.phone.NotificationGroupManager; +import com.android.systemui.statusbar.phone.NotificationShadeWindowControllerImpl; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.ShadeControllerImpl; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; @@ -59,10 +63,9 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl; import com.android.systemui.statusbar.policy.HeadsUpManager; -import com.android.systemui.wmshell.WindowManagerShellModule; +import com.android.systemui.wmshell.WMShellModule; import javax.inject.Named; -import javax.inject.Singleton; import dagger.Binds; import dagger.Module; @@ -75,14 +78,13 @@ import dagger.Provides; @Module(includes = { DividerModule.class, QSModule.class, - WindowManagerShellModule.class + WMShellModule.class }, subcomponents = { - TvSysUIComponent.class }) public abstract class TvSystemUIModule { - @Singleton + @SysUISingleton @Provides @Named(LEAK_REPORT_EMAIL_NAME) @Nullable @@ -98,19 +100,19 @@ public abstract class TvSystemUIModule { NotificationLockscreenUserManagerImpl notificationLockscreenUserManager); @Provides - @Singleton + @SysUISingleton static BatteryController provideBatteryController(Context context, EnhancedEstimates enhancedEstimates, PowerManager powerManager, - BroadcastDispatcher broadcastDispatcher, @Main Handler mainHandler, - @Background Handler bgHandler) { + BroadcastDispatcher broadcastDispatcher, DemoModeController demoModeController, + @Main Handler mainHandler, @Background Handler bgHandler) { BatteryController bC = new BatteryControllerImpl(context, enhancedEstimates, powerManager, - broadcastDispatcher, mainHandler, bgHandler); + broadcastDispatcher, demoModeController, mainHandler, bgHandler); bC.init(); return bC; } @Binds - @Singleton + @SysUISingleton abstract QSFactory bindQSFactory(QSFactoryImpl qsFactoryImpl); @Binds @@ -123,14 +125,14 @@ public abstract class TvSystemUIModule { @Binds abstract ShadeController provideShadeController(ShadeControllerImpl shadeController); - @Singleton + @SysUISingleton @Provides @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) static boolean provideAllowNotificationLongPress() { return true; } - @Singleton + @SysUISingleton @Provides static HeadsUpManagerPhone provideHeadsUpManagerPhone( Context context, @@ -146,7 +148,7 @@ public abstract class TvSystemUIModule { abstract HeadsUpManager bindHeadsUpManagerPhone(HeadsUpManagerPhone headsUpManagerPhone); @Provides - @Singleton + @SysUISingleton static Recents provideRecents(Context context, RecentsImplementation recentsImplementation, CommandQueue commandQueue) { return new Recents(context, recentsImplementation, commandQueue); @@ -161,5 +163,9 @@ public abstract class TvSystemUIModule { StatusBarKeyguardViewManager statusBarKeyguardViewManager); @Binds + abstract NotificationShadeWindowController bindNotificationShadeController( + NotificationShadeWindowControllerImpl notificationShadeWindowController); + + @Binds abstract DozeHost provideDozeHost(DozeServiceHost dozeServiceHost); } diff --git a/packages/SystemUI/src/com/android/systemui/util/FloatingContentCoordinator.kt b/packages/SystemUI/src/com/android/systemui/util/FloatingContentCoordinator.kt index 242f7cde9d3b..f22f59bee42f 100644 --- a/packages/SystemUI/src/com/android/systemui/util/FloatingContentCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/util/FloatingContentCoordinator.kt @@ -2,10 +2,10 @@ package com.android.systemui.util import android.graphics.Rect import android.util.Log +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.util.FloatingContentCoordinator.FloatingContent -import java.util.HashMap +import java.util.* import javax.inject.Inject -import javax.inject.Singleton /** Tag for debug logging. */ private const val TAG = "FloatingCoordinator" @@ -20,7 +20,7 @@ private const val TAG = "FloatingCoordinator" * other content out of the way. [onContentRemoved] should be called when the content is removed or * no longer visible. */ -@Singleton +@SysUISingleton class FloatingContentCoordinator @Inject constructor() { /** diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java index c82b39af4ab3..d278905abacb 100644 --- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java +++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java @@ -25,6 +25,7 @@ import android.view.View; import com.android.keyguard.KeyguardMessageArea; import com.android.keyguard.KeyguardSliceView; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.qs.QSFooterImpl; import com.android.systemui.qs.QSPanel; import com.android.systemui.qs.QuickQSPanel; @@ -38,7 +39,6 @@ import java.lang.reflect.Modifier; import javax.inject.Inject; import javax.inject.Named; -import javax.inject.Singleton; import dagger.BindsInstance; import dagger.Subcomponent; @@ -47,7 +47,7 @@ import dagger.Subcomponent; * Manages inflation that requires dagger injection. * See docs/dagger.md for details. */ -@Singleton +@SysUISingleton public class InjectionInflationController { public static final String VIEW_CONTEXT = "view_context"; diff --git a/packages/SystemUI/src/com/android/systemui/util/RingerModeTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/util/RingerModeTrackerImpl.kt index 58684c386995..751324102036 100644 --- a/packages/SystemUI/src/com/android/systemui/util/RingerModeTrackerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/util/RingerModeTrackerImpl.kt @@ -25,12 +25,12 @@ import android.os.UserHandle import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import java.util.concurrent.Executor import javax.inject.Inject -import javax.inject.Singleton -@Singleton +@SysUISingleton class RingerModeTrackerImpl @Inject constructor( audioManager: AudioManager, broadcastDispatcher: BroadcastDispatcher, diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java index bf22a9897d16..628c808aa12b 100644 --- a/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java +++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java @@ -22,6 +22,7 @@ import android.os.HandlerThread; import android.os.Looper; import android.os.Process; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.LongRunning; import com.android.systemui.dagger.qualifiers.Main; @@ -30,8 +31,6 @@ import com.android.systemui.dagger.qualifiers.UiBackground; import java.util.concurrent.Executor; import java.util.concurrent.Executors; -import javax.inject.Singleton; - import dagger.Binds; import dagger.Module; import dagger.Provides; @@ -43,7 +42,7 @@ import dagger.Provides; public abstract class ConcurrencyModule { /** Background Looper */ @Provides - @Singleton + @SysUISingleton @Background public static Looper provideBgLooper() { HandlerThread thread = new HandlerThread("SysUiBg", @@ -54,7 +53,7 @@ public abstract class ConcurrencyModule { /** Long running tasks Looper */ @Provides - @Singleton + @SysUISingleton @LongRunning public static Looper provideLongRunningLooper() { HandlerThread thread = new HandlerThread("SysUiLng", @@ -96,7 +95,7 @@ public abstract class ConcurrencyModule { * Provide a Background-Thread Executor by default. */ @Provides - @Singleton + @SysUISingleton public static Executor provideExecutor(@Background Looper looper) { return new ExecutorImpl(looper); } @@ -105,7 +104,7 @@ public abstract class ConcurrencyModule { * Provide a Long running Executor by default. */ @Provides - @Singleton + @SysUISingleton @LongRunning public static Executor provideLongRunningExecutor(@LongRunning Looper looper) { return new ExecutorImpl(looper); @@ -115,7 +114,7 @@ public abstract class ConcurrencyModule { * Provide a Background-Thread Executor. */ @Provides - @Singleton + @SysUISingleton @Background public static Executor provideBackgroundExecutor(@Background Looper looper) { return new ExecutorImpl(looper); @@ -134,7 +133,7 @@ public abstract class ConcurrencyModule { * Provide a Background-Thread Executor by default. */ @Provides - @Singleton + @SysUISingleton public static DelayableExecutor provideDelayableExecutor(@Background Looper looper) { return new ExecutorImpl(looper); } @@ -143,7 +142,7 @@ public abstract class ConcurrencyModule { * Provide a Background-Thread Executor. */ @Provides - @Singleton + @SysUISingleton @Background public static DelayableExecutor provideBackgroundDelayableExecutor(@Background Looper looper) { return new ExecutorImpl(looper); @@ -153,7 +152,7 @@ public abstract class ConcurrencyModule { * Provide a Main-Thread Executor. */ @Provides - @Singleton + @SysUISingleton @Main public static DelayableExecutor provideMainDelayableExecutor(@Main Looper looper) { return new ExecutorImpl(looper); @@ -163,7 +162,7 @@ public abstract class ConcurrencyModule { * Provide a Background-Thread Executor by default. */ @Provides - @Singleton + @SysUISingleton public static RepeatableExecutor provideRepeatableExecutor(@Background DelayableExecutor exec) { return new RepeatableExecutorImpl(exec); } @@ -172,7 +171,7 @@ public abstract class ConcurrencyModule { * Provide a Background-Thread Executor. */ @Provides - @Singleton + @SysUISingleton @Background public static RepeatableExecutor provideBackgroundRepeatableExecutor( @Background DelayableExecutor exec) { @@ -183,7 +182,7 @@ public abstract class ConcurrencyModule { * Provide a Main-Thread Executor. */ @Provides - @Singleton + @SysUISingleton @Main public static RepeatableExecutor provideMainRepeatableExecutor(@Main DelayableExecutor exec) { return new RepeatableExecutorImpl(exec); @@ -195,7 +194,7 @@ public abstract class ConcurrencyModule { * Keep submitted runnables short and to the point, just as with any other UI code. */ @Provides - @Singleton + @SysUISingleton @UiBackground public static Executor provideUiBackgroundExecutor() { return Executors.newSingleThreadExecutor(); diff --git a/packages/SystemUI/src/com/android/systemui/util/io/Files.java b/packages/SystemUI/src/com/android/systemui/util/io/Files.java index 7d633a769600..a2d309cf76d4 100644 --- a/packages/SystemUI/src/com/android/systemui/util/io/Files.java +++ b/packages/SystemUI/src/com/android/systemui/util/io/Files.java @@ -18,6 +18,8 @@ package com.android.systemui.util.io; import androidx.annotation.NonNull; +import com.android.systemui.dagger.SysUISingleton; + import java.io.BufferedWriter; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -28,12 +30,11 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.stream.Stream; import javax.inject.Inject; -import javax.inject.Singleton; /** * Wrapper around {@link java.nio.file.Files} that can be mocked in tests. */ -@Singleton +@SysUISingleton public class Files { @Inject public Files() { } diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java index d1805af06434..ba58ed282786 100644 --- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java @@ -48,6 +48,7 @@ import com.android.internal.logging.MetricsLogger; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.SystemUI; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; @@ -63,14 +64,13 @@ import java.util.ArrayList; import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * Suite of tools to periodically inspect the System UI heap and possibly prompt the user to * capture heap dumps and report them. Includes the implementation of the "Dump SysUI Heap" * quick settings tile. */ -@Singleton +@SysUISingleton public class GarbageMonitor implements Dumpable { // Feature switches // ================ @@ -552,7 +552,7 @@ public class GarbageMonitor implements Dumpable { } /** */ - @Singleton + @SysUISingleton public static class Service extends SystemUI implements Dumpable { private final GarbageMonitor mGarbageMonitor; diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java index 5e7280840bb9..f0a4195beebe 100644 --- a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java +++ b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java @@ -34,6 +34,8 @@ import android.util.Log; import androidx.core.content.FileProvider; +import com.android.systemui.dagger.SysUISingleton; + import com.google.android.collect.Lists; import java.io.File; @@ -44,12 +46,11 @@ import java.util.ArrayList; import javax.inject.Inject; import javax.inject.Named; -import javax.inject.Singleton; /** * Dumps data to debug leaks and posts a notification to share the data. */ -@Singleton +@SysUISingleton public class LeakReporter { static final String TAG = "LeakReporter"; diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java b/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java index ed4df175b1a6..48759824f5ef 100644 --- a/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java @@ -29,6 +29,7 @@ import android.os.MemoryFile; import android.util.Log; import com.android.internal.util.Preconditions; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.PluginListener; import com.android.systemui.plugins.SensorManagerPlugin; import com.android.systemui.shared.plugins.PluginManager; @@ -39,7 +40,6 @@ import java.util.List; import java.util.concurrent.Executor; import javax.inject.Inject; -import javax.inject.Singleton; /** * Wrapper around sensor manager that hides potential sources of latency. @@ -48,7 +48,7 @@ import javax.inject.Singleton; * without blocking. Note that this means registering listeners now always appears successful even * if it is not. */ -@Singleton +@SysUISingleton public class AsyncSensorManager extends SensorManager implements PluginListener<SensorManagerPlugin> { diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java index 42393375b45e..e8c5db74f494 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java @@ -18,7 +18,7 @@ package com.android.systemui.volume; import android.content.res.Configuration; -import com.android.systemui.DemoMode; +import com.android.systemui.demomode.DemoMode; import java.io.FileDescriptor; import java.io.PrintWriter; diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java index 1c2a2fa53bea..56f1c092efd9 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java @@ -27,6 +27,9 @@ import android.view.WindowManager.LayoutParams; import com.android.settingslib.applications.InterestingConfigChanges; import com.android.systemui.Dependency; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.demomode.DemoMode; +import com.android.systemui.demomode.DemoModeController; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.PluginDependencyProvider; @@ -38,14 +41,15 @@ import com.android.systemui.tuner.TunerService; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; import javax.inject.Inject; -import javax.inject.Singleton; /** * Implementation of VolumeComponent backed by the new volume dialog. */ -@Singleton +@SysUISingleton public class VolumeDialogComponent implements VolumeComponent, TunerService.Tunable, VolumeDialogControllerImpl.UserActivityListener{ @@ -72,8 +76,11 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna ); @Inject - public VolumeDialogComponent(Context context, KeyguardViewMediator keyguardViewMediator, - VolumeDialogControllerImpl volumeDialogController) { + public VolumeDialogComponent( + Context context, + KeyguardViewMediator keyguardViewMediator, + VolumeDialogControllerImpl volumeDialogController, + DemoModeController demoModeController) { mContext = context; mKeyguardViewMediator = keyguardViewMediator; mController = volumeDialogController; @@ -94,6 +101,7 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna applyConfiguration(); Dependency.get(TunerService.class).addTunable(this, VOLUME_DOWN_SILENT, VOLUME_UP_SILENT, VOLUME_SILENT_DO_NOT_DISTURB); + demoModeController.addCallback(this); } protected VolumeDialog createDefault() { @@ -164,6 +172,13 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna } @Override + public List<String> demoCommands() { + List<String> s = new ArrayList<>(); + s.add(DemoMode.COMMAND_VOLUME); + return s; + } + + @Override public void register() { mController.register(); DndTile.setCombinedIcon(mContext, true); diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java index f19c49cc123f..d8eecef024ce 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java @@ -62,6 +62,7 @@ import com.android.settingslib.volume.MediaSessions; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.plugins.VolumeDialogController; import com.android.systemui.qs.tiles.DndTile; @@ -77,7 +78,6 @@ import java.util.Objects; import java.util.Optional; import javax.inject.Inject; -import javax.inject.Singleton; import dagger.Lazy; @@ -88,7 +88,7 @@ import dagger.Lazy; * * Methods ending in "W" must be called on the worker thread. */ -@Singleton +@SysUISingleton public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpable { private static final String TAG = Util.logTag(VolumeDialogControllerImpl.class); diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java index c0b80417fe14..c378e3bd76c9 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java @@ -23,15 +23,15 @@ import android.util.Log; import com.android.systemui.R; import com.android.systemui.SystemUI; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.qs.tiles.DndTile; import java.io.FileDescriptor; import java.io.PrintWriter; import javax.inject.Inject; -import javax.inject.Singleton; -@Singleton +@SysUISingleton public class VolumeUI extends SystemUI { private static final String TAG = "VolumeUI"; private static boolean LOGD = Log.isLoggable(TAG, Log.DEBUG); diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java new file mode 100644 index 000000000000..ac47660f3221 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java @@ -0,0 +1,58 @@ +/* + * 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.wmshell; + +import android.content.Context; +import android.os.Handler; +import android.view.IWindowManager; + +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.common.SystemWindows; +import com.android.wm.shell.common.TransactionPool; + +import dagger.Module; +import dagger.Provides; + +/** + * Provides basic dependencies from {@link com.android.wm.shell}, the dependencies declared here + * should be shared among different branches of SystemUI. + */ +// TODO(b/162923491): Move most of these dependencies into WMSingleton scope. +@Module +public class WMShellBaseModule { + @SysUISingleton + @Provides + static TransactionPool provideTransactionPool() { + return new TransactionPool(); + } + + @SysUISingleton + @Provides + static DisplayController provideDisplayController(Context context, @Main Handler handler, + IWindowManager wmService) { + return new DisplayController(context, handler, wmService); + } + + @SysUISingleton + @Provides + static SystemWindows provideSystemWindows(DisplayController displayController, + IWindowManager wmService) { + return new SystemWindows(displayController, wmService); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WindowManagerShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java index d2c61cc996dd..44bb6ac5a49c 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WindowManagerShellModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java @@ -16,50 +16,28 @@ package com.android.systemui.wmshell; -import android.content.Context; import android.os.Handler; import android.view.IWindowManager; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.pip.phone.PipMenuActivity; import com.android.systemui.pip.phone.dagger.PipMenuActivityClass; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayImeController; -import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.common.TransactionPool; -import javax.inject.Singleton; - import dagger.Module; import dagger.Provides; /** - * Provides dependencies from {@link com.android.wm.shell}. + * Provides dependencies from {@link com.android.wm.shell} which could be customized among different + * branches of SystemUI. */ -@Module -// TODO(b/161116823) Clean up dependencies after wm shell migration finished. -public class WindowManagerShellModule { - @Singleton - @Provides - static TransactionPool provideTransactionPool() { - return new TransactionPool(); - } - - @Singleton - @Provides - static DisplayController provideDisplayController(Context context, @Main Handler handler, - IWindowManager wmService) { - return new DisplayController(context, handler, wmService); - } - - @Singleton - @Provides - static SystemWindows provideSystemWindows(DisplayController displayController, - IWindowManager wmService) { - return new SystemWindows(displayController, wmService); - } - - @Singleton +// TODO(b/162923491): Move most of these dependencies into WMSingleton scope. +@Module(includes = WMShellBaseModule.class) +public class WMShellModule { + @SysUISingleton @Provides static DisplayImeController provideDisplayImeController(IWindowManager wmService, DisplayController displayController, @Main Handler mainHandler, @@ -69,7 +47,7 @@ public class WindowManagerShellModule { } /** TODO(b/150319024): PipMenuActivity will move to a Window */ - @Singleton + @SysUISingleton @PipMenuActivityClass @Provides static Class<?> providePipMenuActivityClass() { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java index 0d52e4fefd3e..5999e2cdec78 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java @@ -80,7 +80,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase { InjectionInflationController inflationController = new InjectionInflationController( SystemUIFactory.getInstance() - .getRootComponent() + .getSysUIComponent() .createViewInstanceCreatorFactory()); LayoutInflater layoutInflater = inflationController .injectable(LayoutInflater.from(getContext())); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java index aa4db3205d82..446b1228f1bb 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java @@ -66,7 +66,7 @@ public class KeyguardPresentationTest extends SysuiTestCase { InjectionInflationController inflationController = new InjectionInflationController( SystemUIFactory.getInstance() - .getRootComponent() + .getSysUIComponent() .createViewInstanceCreatorFactory()); mLayoutInflater = inflationController.injectable(LayoutInflater.from(mContext)); mLayoutInflater.setPrivateFactory(new LayoutInflater.Factory2() { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java index 560d581c20e7..0bf137689aa1 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java @@ -52,7 +52,7 @@ public class KeyguardStatusViewTest extends SysuiTestCase { mDependency.injectMockDependency(KeyguardUpdateMonitor.class); InjectionInflationController inflationController = new InjectionInflationController( SystemUIFactory.getInstance() - .getRootComponent() + .getSysUIComponent() .createViewInstanceCreatorFactory()); LayoutInflater layoutInflater = inflationController .injectable(LayoutInflater.from(getContext())); diff --git a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java index 35be496d1a2c..5d8e4351cfd9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java @@ -47,7 +47,7 @@ public class DependencyTest extends SysuiTestCase { public void testInitDependency() { Dependency.clearDependencies(); Dependency dependency = - SystemUIFactory.getInstance().getRootComponent().createDependency(); + SystemUIFactory.getInstance().getSysUIComponent().createDependency(); dependency.start(); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java index 60f0cd9da5f2..e967a5d607eb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java @@ -82,8 +82,7 @@ public class ForegroundServiceControllerTest extends SysuiTestCase { allowTestableLooperAsMainThread(); MockitoAnnotations.initMocks(this); - mFsc = new ForegroundServiceController( - mEntryManager, mAppOpsController, mMainHandler); + mFsc = new ForegroundServiceController(mAppOpsController, mMainHandler); mListener = new ForegroundServiceNotificationListener( mContext, mFsc, mEntryManager, mNotifPipeline, mock(ForegroundServiceLifetimeExtender.class), mClock); @@ -115,85 +114,6 @@ public class ForegroundServiceControllerTest extends SysuiTestCase { } @Test - public void testAppOps_appOpChangedBeforeNotificationExists() { - // GIVEN app op exists, but notification doesn't exist in NEM yet - NotificationEntry entry = createFgEntry(); - mFsc.onAppOpChanged( - AppOpsManager.OP_CAMERA, - entry.getSbn().getUid(), - entry.getSbn().getPackageName(), - true); - assertFalse(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA)); - - // WHEN the notification is added - mEntryListener.onPendingEntryAdded(entry); - - // THEN the app op is added to the entry - Assert.assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA)); - } - - @Test - public void testAppOps_appOpAddedToForegroundNotif() { - // GIVEN a notification associated with a foreground service - NotificationEntry entry = addFgEntry(); - when(mEntryManager.getPendingOrActiveNotif(entry.getKey())).thenReturn(entry); - - // WHEN we are notified of a new app op for this notification - mFsc.onAppOpChanged( - AppOpsManager.OP_CAMERA, - entry.getSbn().getUid(), - entry.getSbn().getPackageName(), - true); - - // THEN the app op is added to the entry - Assert.assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA)); - - // THEN notification views are updated since the notification is visible - verify(mEntryManager, times(1)).updateNotifications(anyString()); - } - - @Test - public void testAppOpsAlreadyAdded() { - // GIVEN a foreground service associated notification that already has the correct app op - NotificationEntry entry = addFgEntry(); - entry.mActiveAppOps.add(AppOpsManager.OP_CAMERA); - when(mEntryManager.getPendingOrActiveNotif(entry.getKey())).thenReturn(entry); - - // WHEN we are notified of the same app op for this notification - mFsc.onAppOpChanged( - AppOpsManager.OP_CAMERA, - entry.getSbn().getUid(), - entry.getSbn().getPackageName(), - true); - - // THEN the app op still exists in the notification entry - Assert.assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA)); - - // THEN notification views aren't updated since nothing changed - verify(mEntryManager, never()).updateNotifications(anyString()); - } - - @Test - public void testAppOps_appOpNotAddedToUnrelatedNotif() { - // GIVEN no notification entries correspond to the newly updated appOp - NotificationEntry entry = addFgEntry(); - when(mEntryManager.getPendingOrActiveNotif(entry.getKey())).thenReturn(null); - - // WHEN a new app op is detected - mFsc.onAppOpChanged( - AppOpsManager.OP_CAMERA, - entry.getSbn().getUid(), - entry.getSbn().getPackageName(), - true); - - // THEN we won't see appOps on the entry - Assert.assertFalse(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA)); - - // THEN notification views aren't updated since nothing changed - verify(mEntryManager, never()).updateNotifications(anyString()); - } - - @Test public void testAppOpsCRUD() { // no crash on remove that doesn't exist mFsc.onAppOpChanged(9, 1000, "pkg1", false); diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java index 3687b4ca7889..53bae8657d8f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java @@ -55,7 +55,7 @@ public abstract class SysuiBaseFragmentTest extends BaseFragmentTest { public void SysuiSetup() { SystemUIFactory.createFromConfig(mContext); mDependency = new TestableDependency( - SystemUIFactory.getInstance().getRootComponent().createDependency()); + SystemUIFactory.getInstance().getSysUIComponent().createDependency()); Dependency.setInstance(mDependency); // TODO: Figure out another way to give reference to a SysuiTestableContext. diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java index 08e27841de03..b7175eabab39 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java +++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java @@ -74,7 +74,7 @@ public abstract class SysuiTestCase { public void SysuiSetup() throws Exception { SystemUIFactory.createFromConfig(mContext); mDependency = new TestableDependency( - SystemUIFactory.getInstance().getRootComponent().createDependency()); + SystemUIFactory.getInstance().getSysUIComponent().createDependency()); Dependency.setInstance(mDependency); mFakeBroadcastDispatcher = new FakeBroadcastDispatcher(mContext, mock(Looper.class), mock(Executor.class), mock(DumpManager.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java index b7c198e53cfa..a6dfbbd93178 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java @@ -38,6 +38,7 @@ import androidx.test.filters.MediumTest; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.systemui.SysuiTestCase; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -94,6 +95,11 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { mContext, mController, newValueAnimator()); } + @After + public void tearDown() throws Exception { + mInstrumentation.runOnMainSync(() -> mController.deleteWindowMagnification()); + } + @Test public void enableWindowMagnification_disabled_expectedStartAndEndValues() { enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod); diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java index d4a94c5b9e66..c8566c599108 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java @@ -54,6 +54,7 @@ import android.testing.TestableLooper.RunWithLooper; import com.android.internal.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; import org.junit.Before; @@ -103,8 +104,8 @@ public class AuthControllerTest extends SysuiTestCase { when(mDialog1.isAllowDeviceCredentials()).thenReturn(false); when(mDialog2.isAllowDeviceCredentials()).thenReturn(false); - mAuthController = new TestableAuthController( - context, mock(CommandQueue.class), new MockInjector()); + mAuthController = new TestableAuthController(context, mock(CommandQueue.class), + mock(StatusBarStateController.class), new MockInjector()); mAuthController.start(); } @@ -502,8 +503,9 @@ public class AuthControllerTest extends SysuiTestCase { private int mBuildCount = 0; private PromptInfo mLastBiometricPromptInfo; - TestableAuthController(Context context, CommandQueue commandQueue, Injector injector) { - super(context, commandQueue, injector); + TestableAuthController(Context context, CommandQueue commandQueue, + StatusBarStateController statusBarStateController, Injector injector) { + super(context, commandQueue, statusBarStateController, injector); } @Override 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 5c86fcb6b008..a7808ad54d63 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -60,7 +60,6 @@ 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; @@ -71,9 +70,7 @@ 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; @@ -87,7 +84,7 @@ 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.NotificationShadeWindowControllerImpl; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.policy.BatteryController; @@ -95,7 +92,6 @@ 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; @@ -159,7 +155,7 @@ public class BubbleControllerTest extends SysuiTestCase { private ArgumentCaptor<NotificationRemoveInterceptor> mRemoveInterceptorCaptor; private TestableBubbleController mBubbleController; - private NotificationShadeWindowController mNotificationShadeWindowController; + private NotificationShadeWindowControllerImpl mNotificationShadeWindowController; private NotificationEntryListener mEntryListener; private NotificationRemoveInterceptor mRemoveInterceptor; @@ -199,8 +195,6 @@ public class BubbleControllerTest extends SysuiTestCase { private TestableLooper mTestableLooper; - private SuperStatusBarViewFactory mSuperStatusBarViewFactory; - @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -210,25 +204,8 @@ public class BubbleControllerTest extends SysuiTestCase { mContext.addMockSystemService(FaceManager.class, mFaceManager); when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors); - mSuperStatusBarViewFactory = new SuperStatusBarViewFactory(mContext, - new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent() - .createViewInstanceCreatorFactory()), - 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, + mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(mContext, mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController, mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController, mColorExtractor, mDumpManager); 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 196aa65bd28f..4936360756fd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java @@ -83,7 +83,7 @@ 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.NotificationShadeWindowControllerImpl; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.policy.BatteryController; @@ -153,7 +153,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { @Captor private ArgumentCaptor<NotifCollectionListener> mNotifListenerCaptor; private TestableBubbleController mBubbleController; - private NotificationShadeWindowController mNotificationShadeWindowController; + private NotificationShadeWindowControllerImpl mNotificationShadeWindowController; private NotifCollectionListener mEntryListener; private NotificationTestHelper mNotificationTestHelper; private ExpandableNotificationRow mRow; @@ -201,7 +201,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors); mSuperStatusBarViewFactory = new SuperStatusBarViewFactory(mContext, - new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent() + new InjectionInflationController(SystemUIFactory.getInstance().getSysUIComponent() .createViewInstanceCreatorFactory()), new NotificationShelfComponent.Builder() { @Override @@ -218,7 +218,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { mLockIconController); // Bubbles get added to status bar window view - mNotificationShadeWindowController = new NotificationShadeWindowController(mContext, + mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(mContext, mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController, mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController, mColorExtractor, mDumpManager); diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java index 0a6d0716cb85..51ca2a4e5966 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java @@ -27,11 +27,11 @@ 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.NotificationShadeWindowController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.phone.NotificationGroupManager; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ZenModeController; diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java index 4c5495474018..c8e0f490a783 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java @@ -71,7 +71,7 @@ import com.android.systemui.plugins.GlobalActions; import com.android.systemui.plugins.GlobalActionsPanelPlugin; import com.android.systemui.settings.CurrentUserContextTracker; import com.android.systemui.statusbar.NotificationShadeDepthController; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.RingerModeLiveData; diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java index 2e794a40d238..89538ac8bc9f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java @@ -20,7 +20,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; @@ -34,19 +33,23 @@ import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; -import java.util.Map; @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper public class MediaDataCombineLatestTest extends SysuiTestCase { + @Rule public MockitoRule mockito = MockitoJUnit.rule(); + private static final String KEY = "TEST_KEY"; private static final String OLD_KEY = "TEST_KEY_OLD"; private static final String APP = "APP"; @@ -59,27 +62,14 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { private MediaDataCombineLatest mManager; - @Mock private MediaDataManager mDataSource; - @Mock private MediaDeviceManager mDeviceSource; @Mock private MediaDataManager.Listener mListener; - private MediaDataManager.Listener mDataListener; - private MediaDeviceManager.Listener mDeviceListener; - private MediaData mMediaData; private MediaDeviceData mDeviceData; @Before public void setUp() { - mDataSource = mock(MediaDataManager.class); - mDeviceSource = mock(MediaDeviceManager.class); - mListener = mock(MediaDataManager.Listener.class); - - mManager = new MediaDataCombineLatest(mDataSource, mDeviceSource); - - mDataListener = captureDataListener(); - mDeviceListener = captureDeviceListener(); - + mManager = new MediaDataCombineLatest(); mManager.addListener(mListener); mMediaData = new MediaData(USER_ID, true, BG_COLOR, APP, null, ARTIST, TITLE, null, @@ -91,7 +81,7 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { @Test public void eventNotEmittedWithoutDevice() { // WHEN data source emits an event without device data - mDataListener.onMediaDataLoaded(KEY, null, mMediaData); + mManager.onMediaDataLoaded(KEY, null, mMediaData); // THEN an event isn't emitted verify(mListener, never()).onMediaDataLoaded(eq(KEY), any(), any()); } @@ -99,7 +89,7 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { @Test public void eventNotEmittedWithoutMedia() { // WHEN device source emits an event without media data - mDeviceListener.onMediaDeviceChanged(KEY, null, mDeviceData); + mManager.onMediaDeviceChanged(KEY, null, mDeviceData); // THEN an event isn't emitted verify(mListener, never()).onMediaDataLoaded(eq(KEY), any(), any()); } @@ -107,9 +97,9 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { @Test public void emitEventAfterDeviceFirst() { // GIVEN that a device event has already been received - mDeviceListener.onMediaDeviceChanged(KEY, null, mDeviceData); + mManager.onMediaDeviceChanged(KEY, null, mDeviceData); // WHEN media event is received - mDataListener.onMediaDataLoaded(KEY, null, mMediaData); + mManager.onMediaDataLoaded(KEY, null, mMediaData); // THEN the listener receives a combined event ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), any(), captor.capture()); @@ -119,9 +109,9 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { @Test public void emitEventAfterMediaFirst() { // GIVEN that media event has already been received - mDataListener.onMediaDataLoaded(KEY, null, mMediaData); + mManager.onMediaDataLoaded(KEY, null, mMediaData); // WHEN device event is received - mDeviceListener.onMediaDeviceChanged(KEY, null, mDeviceData); + mManager.onMediaDeviceChanged(KEY, null, mDeviceData); // THEN the listener receives a combined event ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), any(), captor.capture()); @@ -131,11 +121,11 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { @Test public void migrateKeyMediaFirst() { // GIVEN that media and device info has already been received - mDataListener.onMediaDataLoaded(OLD_KEY, null, mMediaData); - mDeviceListener.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); + mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData); + mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); reset(mListener); // WHEN a key migration event is received - mDataListener.onMediaDataLoaded(KEY, OLD_KEY, mMediaData); + mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData); // THEN the listener receives a combined event ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), eq(OLD_KEY), captor.capture()); @@ -145,11 +135,11 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { @Test public void migrateKeyDeviceFirst() { // GIVEN that media and device info has already been received - mDataListener.onMediaDataLoaded(OLD_KEY, null, mMediaData); - mDeviceListener.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); + mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData); + mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); reset(mListener); // WHEN a key migration event is received - mDeviceListener.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData); + mManager.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData); // THEN the listener receives a combined event ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), eq(OLD_KEY), captor.capture()); @@ -159,12 +149,12 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { @Test public void migrateKeyMediaAfter() { // GIVEN that media and device info has already been received - mDataListener.onMediaDataLoaded(OLD_KEY, null, mMediaData); - mDeviceListener.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); - mDeviceListener.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData); + mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData); + mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); + mManager.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData); reset(mListener); // WHEN a second key migration event is received for media - mDataListener.onMediaDataLoaded(KEY, OLD_KEY, mMediaData); + mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData); // THEN the key has already been migrated ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), eq(KEY), captor.capture()); @@ -174,12 +164,12 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { @Test public void migrateKeyDeviceAfter() { // GIVEN that media and device info has already been received - mDataListener.onMediaDataLoaded(OLD_KEY, null, mMediaData); - mDeviceListener.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); - mDataListener.onMediaDataLoaded(KEY, OLD_KEY, mMediaData); + mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData); + mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); + mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData); reset(mListener); // WHEN a second key migration event is received for the device - mDeviceListener.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData); + mManager.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData); // THEN the key has already be migrated ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), eq(KEY), captor.capture()); @@ -189,60 +179,34 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { @Test public void mediaDataRemoved() { // WHEN media data is removed without first receiving device or data - mDataListener.onMediaDataRemoved(KEY); + mManager.onMediaDataRemoved(KEY); // THEN a removed event isn't emitted verify(mListener, never()).onMediaDataRemoved(eq(KEY)); } @Test public void mediaDataRemovedAfterMediaEvent() { - mDataListener.onMediaDataLoaded(KEY, null, mMediaData); - mDataListener.onMediaDataRemoved(KEY); + mManager.onMediaDataLoaded(KEY, null, mMediaData); + mManager.onMediaDataRemoved(KEY); verify(mListener).onMediaDataRemoved(eq(KEY)); } @Test public void mediaDataRemovedAfterDeviceEvent() { - mDeviceListener.onMediaDeviceChanged(KEY, null, mDeviceData); - mDataListener.onMediaDataRemoved(KEY); + mManager.onMediaDeviceChanged(KEY, null, mDeviceData); + mManager.onMediaDataRemoved(KEY); verify(mListener).onMediaDataRemoved(eq(KEY)); } @Test public void mediaDataKeyUpdated() { // GIVEN that device and media events have already been received - mDataListener.onMediaDataLoaded(KEY, null, mMediaData); - mDeviceListener.onMediaDeviceChanged(KEY, null, mDeviceData); + mManager.onMediaDataLoaded(KEY, null, mMediaData); + mManager.onMediaDeviceChanged(KEY, null, mDeviceData); // WHEN the key is changed - mDataListener.onMediaDataLoaded("NEW_KEY", KEY, mMediaData); + mManager.onMediaDataLoaded("NEW_KEY", KEY, mMediaData); // THEN the listener gets a load event with the correct keys ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq("NEW_KEY"), any(), captor.capture()); } - - @Test - public void getDataIncludesDevice() { - // GIVEN that device and media events have been received - mDeviceListener.onMediaDeviceChanged(KEY, null, mDeviceData); - mDataListener.onMediaDataLoaded(KEY, null, mMediaData); - - // THEN the result of getData includes device info - Map<String, MediaData> results = mManager.getData(); - assertThat(results.get(KEY)).isNotNull(); - assertThat(results.get(KEY).getDevice()).isEqualTo(mDeviceData); - } - - private MediaDataManager.Listener captureDataListener() { - ArgumentCaptor<MediaDataManager.Listener> captor = ArgumentCaptor.forClass( - MediaDataManager.Listener.class); - verify(mDataSource).addListener(captor.capture()); - return captor.getValue(); - } - - private MediaDeviceManager.Listener captureDeviceListener() { - ArgumentCaptor<MediaDeviceManager.Listener> captor = ArgumentCaptor.forClass( - MediaDeviceManager.Listener.class); - verify(mDeviceSource).addListener(captor.capture()); - return captor.getValue(); - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt index afb64a7649b4..36b6527167f2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt @@ -32,6 +32,7 @@ import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.`when` import org.mockito.Mockito.never +import org.mockito.Mockito.reset import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations import java.util.concurrent.Executor @@ -56,8 +57,6 @@ private fun <T> any(): T = Mockito.any() class MediaDataFilterTest : SysuiTestCase() { @Mock - private lateinit var combineLatest: MediaDataCombineLatest - @Mock private lateinit var listener: MediaDataManager.Listener @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher @@ -78,8 +77,9 @@ class MediaDataFilterTest : SysuiTestCase() { @Before fun setup() { MockitoAnnotations.initMocks(this) - mediaDataFilter = MediaDataFilter(combineLatest, broadcastDispatcher, mediaResumeListener, - mediaDataManager, lockscreenUserManager, executor) + mediaDataFilter = MediaDataFilter(broadcastDispatcher, mediaResumeListener, + lockscreenUserManager, executor) + mediaDataFilter.mediaDataManager = mediaDataManager mediaDataFilter.addListener(listener) // Start all tests as main user @@ -152,8 +152,9 @@ class MediaDataFilterTest : SysuiTestCase() { @Test fun testOnUserSwitched_addsNewUserControls() { // GIVEN that we had some media for both users - val dataMap = mapOf(KEY to dataMain, KEY_ALT to dataGuest) - `when`(combineLatest.getData()).thenReturn(dataMap) + mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain) + mediaDataFilter.onMediaDataLoaded(KEY_ALT, null, dataGuest) + reset(listener) // and we switch to guest user setUser(USER_GUEST) @@ -213,4 +214,4 @@ class MediaDataFilterTest : SysuiTestCase() { verify(mediaDataManager).setTimedOut(eq(KEY), eq(true)) } -}
\ No newline at end of file +} 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 457d559449e1..84c1bf932b5e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt @@ -16,6 +16,7 @@ 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.capture import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat @@ -24,9 +25,13 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.mock +import org.mockito.Mockito.never +import org.mockito.Mockito.reset import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit import org.mockito.Mockito.`when` as whenever @@ -48,6 +53,7 @@ private fun <T> anyObject(): T { @RunWith(AndroidTestingRunner::class) class MediaDataManagerTest : SysuiTestCase() { + @JvmField @Rule val mockito = MockitoJUnit.rule() @Mock lateinit var mediaControllerFactory: MediaControllerFactory @Mock lateinit var controller: MediaController lateinit var session: MediaSession @@ -58,20 +64,38 @@ class MediaDataManagerTest : SysuiTestCase() { @Mock lateinit var broadcastDispatcher: BroadcastDispatcher @Mock lateinit var mediaTimeoutListener: MediaTimeoutListener @Mock lateinit var mediaResumeListener: MediaResumeListener + @Mock lateinit var mediaSessionBasedFilter: MediaSessionBasedFilter + @Mock lateinit var mediaDeviceManager: MediaDeviceManager + @Mock lateinit var mediaDataCombineLatest: MediaDataCombineLatest + @Mock lateinit var mediaDataFilter: MediaDataFilter + @Mock lateinit var listener: MediaDataManager.Listener @Mock lateinit var pendingIntent: PendingIntent @Mock lateinit var activityStarter: ActivityStarter - @JvmField @Rule val mockito = MockitoJUnit.rule() lateinit var mediaDataManager: MediaDataManager lateinit var mediaNotification: StatusBarNotification + @Captor lateinit var mediaDataCaptor: ArgumentCaptor<MediaData> @Before fun setup() { foregroundExecutor = FakeExecutor(FakeSystemClock()) backgroundExecutor = FakeExecutor(FakeSystemClock()) - mediaDataManager = MediaDataManager(context, backgroundExecutor, foregroundExecutor, - mediaControllerFactory, broadcastDispatcher, dumpManager, - mediaTimeoutListener, mediaResumeListener, activityStarter, - useMediaResumption = true, useQsMediaPlayer = true) + mediaDataManager = MediaDataManager( + context = context, + backgroundExecutor = backgroundExecutor, + foregroundExecutor = foregroundExecutor, + mediaControllerFactory = mediaControllerFactory, + broadcastDispatcher = broadcastDispatcher, + dumpManager = dumpManager, + mediaTimeoutListener = mediaTimeoutListener, + mediaResumeListener = mediaResumeListener, + mediaSessionBasedFilter = mediaSessionBasedFilter, + mediaDeviceManager = mediaDeviceManager, + mediaDataCombineLatest = mediaDataCombineLatest, + mediaDataFilter = mediaDataFilter, + activityStarter = activityStarter, + useMediaResumption = true, + useQsMediaPlayer = true + ) session = MediaSession(context, "MediaDataManagerTestSession") mediaNotification = SbnBuilder().run { setPkg(PACKAGE_NAME) @@ -86,6 +110,12 @@ class MediaDataManagerTest : SysuiTestCase() { putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE) } whenever(mediaControllerFactory.create(eq(session.sessionToken))).thenReturn(controller) + + // This is an ugly hack for now. The mediaSessionBasedFilter is one of the internal + // listeners in the internal processing pipeline. It receives events, but ince it is a + // mock, it doesn't pass those events along the chain to the external listeners. So, just + // treat mediaSessionBasedFilter as a listener for testing. + listener = mediaSessionBasedFilter } @After @@ -115,8 +145,6 @@ class MediaDataManagerTest : SysuiTestCase() { @Test fun testOnMetaDataLoaded_callsListener() { - val listener = mock(MediaDataManager.Listener::class.java) - mediaDataManager.addListener(listener) mediaDataManager.onNotificationAdded(KEY, mediaNotification) mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = mock(MediaData::class.java)) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), anyObject()) @@ -124,90 +152,81 @@ class MediaDataManagerTest : SysuiTestCase() { @Test fun testOnMetaDataLoaded_conservesActiveFlag() { - val listener = TestListener() whenever(mediaControllerFactory.create(anyObject())).thenReturn(controller) whenever(controller.metadata).thenReturn(metadataBuilder.build()) mediaDataManager.addListener(listener) mediaDataManager.onNotificationAdded(KEY, mediaNotification) assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) - assertThat(listener.data!!.active).isTrue() + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor)) + assertThat(mediaDataCaptor.value!!.active).isTrue() } @Test fun testOnNotificationRemoved_callsListener() { - val listener = mock(MediaDataManager.Listener::class.java) - mediaDataManager.addListener(listener) mediaDataManager.onNotificationAdded(KEY, mediaNotification) mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = mock(MediaData::class.java)) mediaDataManager.onNotificationRemoved(KEY) - verify(listener).onMediaDataRemoved(eq(KEY)) } @Test fun testOnNotificationRemoved_withResumption() { // GIVEN that the manager has a notification with a resume action - val listener = TestListener() - mediaDataManager.addListener(listener) whenever(controller.metadata).thenReturn(metadataBuilder.build()) mediaDataManager.onNotificationAdded(KEY, mediaNotification) assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) - val data = listener.data!! + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor)) + val data = mediaDataCaptor.value assertThat(data.resumption).isFalse() mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {})) // WHEN the notification is removed mediaDataManager.onNotificationRemoved(KEY) // THEN the media data indicates that it is for resumption - assertThat(listener.data!!.resumption).isTrue() - // AND the new key is the package name - assertThat(listener.key!!).isEqualTo(PACKAGE_NAME) - assertThat(listener.oldKey!!).isEqualTo(KEY) - assertThat(listener.removedKey).isNull() + verify(listener).onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor)) + assertThat(mediaDataCaptor.value.resumption).isTrue() } @Test fun testOnNotificationRemoved_twoWithResumption() { // GIVEN that the manager has two notifications with resume actions - val listener = TestListener() - mediaDataManager.addListener(listener) whenever(controller.metadata).thenReturn(metadataBuilder.build()) mediaDataManager.onNotificationAdded(KEY, mediaNotification) mediaDataManager.onNotificationAdded(KEY_2, mediaNotification) assertThat(backgroundExecutor.runAllReady()).isEqualTo(2) assertThat(foregroundExecutor.runAllReady()).isEqualTo(2) - val data = listener.data!! + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor)) + val data = mediaDataCaptor.value assertThat(data.resumption).isFalse() val resumableData = data.copy(resumeAction = Runnable {}) mediaDataManager.onMediaDataLoaded(KEY, null, resumableData) mediaDataManager.onMediaDataLoaded(KEY_2, null, resumableData) + reset(listener) // WHEN the first is removed mediaDataManager.onNotificationRemoved(KEY) // THEN the data is for resumption and the key is migrated to the package name - assertThat(listener.data!!.resumption).isTrue() - assertThat(listener.key!!).isEqualTo(PACKAGE_NAME) - assertThat(listener.oldKey!!).isEqualTo(KEY) - assertThat(listener.removedKey).isNull() + verify(listener).onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor)) + assertThat(mediaDataCaptor.value.resumption).isTrue() + verify(listener, never()).onMediaDataRemoved(eq(KEY)) // WHEN the second is removed mediaDataManager.onNotificationRemoved(KEY_2) // THEN the data is for resumption and the second key is removed - assertThat(listener.data!!.resumption).isTrue() - assertThat(listener.key!!).isEqualTo(PACKAGE_NAME) - assertThat(listener.oldKey!!).isEqualTo(PACKAGE_NAME) - assertThat(listener.removedKey!!).isEqualTo(KEY_2) + verify(listener).onMediaDataLoaded(eq(PACKAGE_NAME), eq(PACKAGE_NAME), + capture(mediaDataCaptor)) + assertThat(mediaDataCaptor.value.resumption).isTrue() + verify(listener).onMediaDataRemoved(eq(KEY_2)) } @Test fun testAppBlockedFromResumption() { // GIVEN that the manager has a notification with a resume action - val listener = TestListener() - mediaDataManager.addListener(listener) whenever(controller.metadata).thenReturn(metadataBuilder.build()) mediaDataManager.onNotificationAdded(KEY, mediaNotification) assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) - val data = listener.data!! + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor)) + val data = mediaDataCaptor.value assertThat(data.resumption).isFalse() mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {})) @@ -219,7 +238,7 @@ class MediaDataManagerTest : SysuiTestCase() { mediaDataManager.onNotificationRemoved(KEY) // THEN the media data is removed - assertThat(listener.removedKey!!).isEqualTo(KEY) + verify(listener).onMediaDataRemoved(eq(KEY)) } @Test @@ -229,13 +248,12 @@ class MediaDataManagerTest : SysuiTestCase() { mediaDataManager.appsBlockedFromResume = blocked // and GIVEN that the manager has a notification from that app with a resume action - val listener = TestListener() - mediaDataManager.addListener(listener) whenever(controller.metadata).thenReturn(metadataBuilder.build()) mediaDataManager.onNotificationAdded(KEY, mediaNotification) assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) - val data = listener.data!! + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor)) + val data = mediaDataCaptor.value assertThat(data.resumption).isFalse() mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {})) @@ -246,14 +264,11 @@ class MediaDataManagerTest : SysuiTestCase() { mediaDataManager.onNotificationRemoved(KEY) // THEN the entry will stay as a resume control - assertThat(listener.key!!).isEqualTo(PACKAGE_NAME) - assertThat(listener.oldKey!!).isEqualTo(KEY) + verify(listener).onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor)) } @Test fun testAddResumptionControls() { - val listener = TestListener() - mediaDataManager.addListener(listener) // WHEN resumption controls are added` val desc = MediaDescription.Builder().run { setTitle(SESSION_TITLE) @@ -264,7 +279,8 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) // THEN the media data indicates that it is for resumption - val data = listener.data!! + verify(listener).onMediaDataLoaded(eq(PACKAGE_NAME), eq(null), capture(mediaDataCaptor)) + val data = mediaDataCaptor.value assertThat(data.resumption).isTrue() assertThat(data.song).isEqualTo(SESSION_TITLE) assertThat(data.app).isEqualTo(APP_NAME) @@ -273,8 +289,6 @@ class MediaDataManagerTest : SysuiTestCase() { @Test fun testDismissMedia_listenerCalled() { - val listener = mock(MediaDataManager.Listener::class.java) - mediaDataManager.addListener(listener) mediaDataManager.onNotificationAdded(KEY, mediaNotification) mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = mock(MediaData::class.java)) mediaDataManager.dismissMediaData(KEY, 0L) @@ -284,26 +298,4 @@ class MediaDataManagerTest : SysuiTestCase() { verify(listener).onMediaDataRemoved(eq(KEY)) } - - /** - * Simple implementation of [MediaDataManager.Listener] for the test. - * - * Giving up on trying to get a mock Listener and ArgumentCaptor to work. - */ - private class TestListener : MediaDataManager.Listener { - var data: MediaData? = null - var key: String? = null - var oldKey: String? = null - var removedKey: String? = null - - override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) { - this.key = key - this.oldKey = oldKey - this.data = data - } - - override fun onMediaDataRemoved(key: String) { - removedKey = key - } - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt index 7bc15dd46cd6..fdb432cc097c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt @@ -68,7 +68,6 @@ private fun <T> eq(value: T): T = Mockito.eq(value) ?: value public class MediaDeviceManagerTest : SysuiTestCase() { private lateinit var manager: MediaDeviceManager - @Mock private lateinit var mediaDataManager: MediaDataManager @Mock private lateinit var lmmFactory: LocalMediaManagerFactory @Mock private lateinit var lmm: LocalMediaManager @Mock private lateinit var mr2: MediaRouter2Manager @@ -91,7 +90,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() { fakeFgExecutor = FakeExecutor(FakeSystemClock()) fakeBgExecutor = FakeExecutor(FakeSystemClock()) manager = MediaDeviceManager(context, lmmFactory, mr2, fakeFgExecutor, fakeBgExecutor, - mediaDataManager, dumpster) + dumpster) manager.addListener(listener) // Configure mocks. diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt index 118cffc2d5b8..ca8f79d08ef0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt @@ -44,11 +44,11 @@ public class MediaPlayerDataTest : SysuiTestCase() { fun addPlayingThenRemote() { val playerIsPlaying = mock(MediaControlPanel::class.java) whenever(playerIsPlaying.isPlaying).thenReturn(true) - val dataIsPlaying = createMediaData(LOCAL, !RESUMPTION) + val dataIsPlaying = createMediaData("app1", LOCAL, !RESUMPTION) val playerIsRemote = mock(MediaControlPanel::class.java) whenever(playerIsRemote.isPlaying).thenReturn(false) - val dataIsRemote = createMediaData(!LOCAL, !RESUMPTION) + val dataIsRemote = createMediaData("app2", !LOCAL, !RESUMPTION) MediaPlayerData.addMediaPlayer("1", dataIsPlaying, playerIsPlaying) MediaPlayerData.addMediaPlayer("2", dataIsRemote, playerIsRemote) @@ -62,11 +62,11 @@ public class MediaPlayerDataTest : SysuiTestCase() { fun switchPlayersPlaying() { val playerIsPlaying1 = mock(MediaControlPanel::class.java) whenever(playerIsPlaying1.isPlaying).thenReturn(true) - val dataIsPlaying1 = createMediaData(LOCAL, !RESUMPTION) + val dataIsPlaying1 = createMediaData("app1", LOCAL, !RESUMPTION) val playerIsPlaying2 = mock(MediaControlPanel::class.java) whenever(playerIsPlaying2.isPlaying).thenReturn(false) - val dataIsPlaying2 = createMediaData(LOCAL, !RESUMPTION) + val dataIsPlaying2 = createMediaData("app2", LOCAL, !RESUMPTION) MediaPlayerData.addMediaPlayer("1", dataIsPlaying1, playerIsPlaying1) MediaPlayerData.addMediaPlayer("2", dataIsPlaying2, playerIsPlaying2) @@ -86,23 +86,23 @@ public class MediaPlayerDataTest : SysuiTestCase() { fun fullOrderTest() { val playerIsPlaying = mock(MediaControlPanel::class.java) whenever(playerIsPlaying.isPlaying).thenReturn(true) - val dataIsPlaying = createMediaData(LOCAL, !RESUMPTION) + val dataIsPlaying = createMediaData("app1", LOCAL, !RESUMPTION) val playerIsPlayingAndRemote = mock(MediaControlPanel::class.java) whenever(playerIsPlayingAndRemote.isPlaying).thenReturn(true) - val dataIsPlayingAndRemote = createMediaData(!LOCAL, !RESUMPTION) + val dataIsPlayingAndRemote = createMediaData("app2", !LOCAL, !RESUMPTION) val playerIsStoppedAndLocal = mock(MediaControlPanel::class.java) whenever(playerIsStoppedAndLocal.isPlaying).thenReturn(false) - val dataIsStoppedAndLocal = createMediaData(LOCAL, !RESUMPTION) + val dataIsStoppedAndLocal = createMediaData("app3", LOCAL, !RESUMPTION) val playerIsStoppedAndRemote = mock(MediaControlPanel::class.java) whenever(playerIsStoppedAndLocal.isPlaying).thenReturn(false) - val dataIsStoppedAndRemote = createMediaData(!LOCAL, !RESUMPTION) + val dataIsStoppedAndRemote = createMediaData("app4", !LOCAL, !RESUMPTION) val playerCanResume = mock(MediaControlPanel::class.java) whenever(playerCanResume.isPlaying).thenReturn(false) - val dataCanResume = createMediaData(LOCAL, RESUMPTION) + val dataCanResume = createMediaData("app5", LOCAL, RESUMPTION) MediaPlayerData.addMediaPlayer("3", dataIsStoppedAndLocal, playerIsStoppedAndLocal) MediaPlayerData.addMediaPlayer("5", dataIsStoppedAndRemote, playerIsStoppedAndRemote) @@ -116,7 +116,7 @@ public class MediaPlayerDataTest : SysuiTestCase() { playerIsStoppedAndLocal, playerCanResume, playerIsStoppedAndRemote).inOrder() } - private fun createMediaData(isLocalSession: Boolean, resumption: Boolean) = - MediaData(0, false, 0, null, null, null, null, null, emptyList(), emptyList<Int>(), "", + private fun createMediaData(app: String, isLocalSession: Boolean, resumption: Boolean) = + MediaData(0, false, 0, app, null, null, null, null, emptyList(), emptyList<Int>(), "", null, null, null, true, null, isLocalSession, resumption, null, false) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt new file mode 100644 index 000000000000..887cc777d4fe --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt @@ -0,0 +1,383 @@ +/* + * 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.media + +import android.graphics.Color +import android.media.session.MediaController +import android.media.session.MediaController.PlaybackInfo +import android.media.session.MediaSession +import android.media.session.MediaSessionManager +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import androidx.test.filters.SmallTest + +import com.android.systemui.SysuiTestCase +import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.mockito.eq +import com.android.systemui.util.time.FakeSystemClock + +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.Mock +import org.mockito.Mockito +import org.mockito.Mockito.any +import org.mockito.Mockito.never +import org.mockito.Mockito.reset +import org.mockito.Mockito.verify +import org.mockito.junit.MockitoJUnit +import org.mockito.Mockito.`when` as whenever + +private const val PACKAGE = "PKG" +private const val KEY = "TEST_KEY" +private const val NOTIF_KEY = "TEST_KEY" +private const val SESSION_ARTIST = "SESSION_ARTIST" +private const val SESSION_TITLE = "SESSION_TITLE" +private const val APP_NAME = "APP_NAME" +private const val USER_ID = 0 + +private val info = MediaData( + userId = USER_ID, + initialized = true, + backgroundColor = Color.DKGRAY, + app = APP_NAME, + appIcon = null, + artist = SESSION_ARTIST, + song = SESSION_TITLE, + artwork = null, + actions = emptyList(), + actionsToShowInCompact = emptyList(), + packageName = PACKAGE, + token = null, + clickIntent = null, + device = null, + active = true, + resumeAction = null, + resumption = false, + notificationKey = NOTIF_KEY, + hasCheckedForResume = false +) + +private fun <T> eq(value: T): T = Mockito.eq(value) ?: value + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper +public class MediaSessionBasedFilterTest : SysuiTestCase() { + + @JvmField @Rule val mockito = MockitoJUnit.rule() + + // Unit to be tested + private lateinit var filter: MediaSessionBasedFilter + + private lateinit var sessionListener: MediaSessionManager.OnActiveSessionsChangedListener + @Mock private lateinit var mediaListener: MediaDataManager.Listener + + // MediaSessionBasedFilter dependencies + @Mock private lateinit var mediaSessionManager: MediaSessionManager + private lateinit var fgExecutor: FakeExecutor + private lateinit var bgExecutor: FakeExecutor + + @Mock private lateinit var controller1: MediaController + @Mock private lateinit var controller2: MediaController + @Mock private lateinit var controller3: MediaController + @Mock private lateinit var controller4: MediaController + + private lateinit var token1: MediaSession.Token + private lateinit var token2: MediaSession.Token + private lateinit var token3: MediaSession.Token + private lateinit var token4: MediaSession.Token + + @Mock private lateinit var remotePlaybackInfo: PlaybackInfo + @Mock private lateinit var localPlaybackInfo: PlaybackInfo + + private lateinit var session1: MediaSession + private lateinit var session2: MediaSession + private lateinit var session3: MediaSession + private lateinit var session4: MediaSession + + private lateinit var mediaData1: MediaData + private lateinit var mediaData2: MediaData + private lateinit var mediaData3: MediaData + private lateinit var mediaData4: MediaData + + @Before + fun setUp() { + fgExecutor = FakeExecutor(FakeSystemClock()) + bgExecutor = FakeExecutor(FakeSystemClock()) + filter = MediaSessionBasedFilter(context, mediaSessionManager, fgExecutor, bgExecutor) + + // Configure mocks. + whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(emptyList()) + + session1 = MediaSession(context, "MediaSessionBasedFilter1") + session2 = MediaSession(context, "MediaSessionBasedFilter2") + session3 = MediaSession(context, "MediaSessionBasedFilter3") + session4 = MediaSession(context, "MediaSessionBasedFilter4") + + token1 = session1.sessionToken + token2 = session2.sessionToken + token3 = session3.sessionToken + token4 = session4.sessionToken + + whenever(controller1.getSessionToken()).thenReturn(token1) + whenever(controller2.getSessionToken()).thenReturn(token2) + whenever(controller3.getSessionToken()).thenReturn(token3) + whenever(controller4.getSessionToken()).thenReturn(token4) + + whenever(controller1.getPackageName()).thenReturn(PACKAGE) + whenever(controller2.getPackageName()).thenReturn(PACKAGE) + whenever(controller3.getPackageName()).thenReturn(PACKAGE) + whenever(controller4.getPackageName()).thenReturn(PACKAGE) + + mediaData1 = info.copy(token = token1) + mediaData2 = info.copy(token = token2) + mediaData3 = info.copy(token = token3) + mediaData4 = info.copy(token = token4) + + whenever(remotePlaybackInfo.getPlaybackType()).thenReturn(PlaybackInfo.PLAYBACK_TYPE_REMOTE) + whenever(localPlaybackInfo.getPlaybackType()).thenReturn(PlaybackInfo.PLAYBACK_TYPE_LOCAL) + + whenever(controller1.getPlaybackInfo()).thenReturn(localPlaybackInfo) + whenever(controller2.getPlaybackInfo()).thenReturn(localPlaybackInfo) + whenever(controller3.getPlaybackInfo()).thenReturn(localPlaybackInfo) + whenever(controller4.getPlaybackInfo()).thenReturn(localPlaybackInfo) + + // Capture listener + bgExecutor.runAllReady() + val listenerCaptor = ArgumentCaptor.forClass( + MediaSessionManager.OnActiveSessionsChangedListener::class.java) + verify(mediaSessionManager).addOnActiveSessionsChangedListener( + listenerCaptor.capture(), any()) + sessionListener = listenerCaptor.value + + filter.addListener(mediaListener) + } + + @After + fun tearDown() { + session1.release() + session2.release() + session3.release() + session4.release() + } + + @Test + fun noMediaSession_loadedEventNotFiltered() { + filter.onMediaDataLoaded(KEY, null, mediaData1) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1)) + } + + @Test + fun noMediaSession_removedEventNotFiltered() { + filter.onMediaDataRemoved(KEY) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + verify(mediaListener).onMediaDataRemoved(eq(KEY)) + } + + @Test + fun matchingMediaSession_loadedEventNotFiltered() { + // GIVEN an active session + val controllers = listOf(controller1) + whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers) + sessionListener.onActiveSessionsChanged(controllers) + // WHEN a loaded event is received that matches the session + filter.onMediaDataLoaded(KEY, null, mediaData1) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + // THEN the event is not filtered + verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1)) + } + + @Test + fun matchingMediaSession_removedEventNotFiltered() { + // GIVEN an active session + val controllers = listOf(controller1) + whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers) + sessionListener.onActiveSessionsChanged(controllers) + // WHEN a removed event is received + filter.onMediaDataRemoved(KEY) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + // THEN the event is not filtered + verify(mediaListener).onMediaDataRemoved(eq(KEY)) + } + + @Test + fun remoteSession_loadedEventNotFiltered() { + // GIVEN a remove session + whenever(controller1.getPlaybackInfo()).thenReturn(remotePlaybackInfo) + val controllers = listOf(controller1) + whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers) + sessionListener.onActiveSessionsChanged(controllers) + // WHEN a loaded event is received that matche the session + filter.onMediaDataLoaded(KEY, null, mediaData1) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + // THEN the event is not filtered + verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1)) + } + + @Test + fun remoteAndLocalSessions_localLoadedEventFiltered() { + // GIVEN remote and local sessions + whenever(controller1.getPlaybackInfo()).thenReturn(remotePlaybackInfo) + val controllers = listOf(controller1, controller2) + whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers) + sessionListener.onActiveSessionsChanged(controllers) + // WHEN a loaded event is received that matches the remote session + filter.onMediaDataLoaded(KEY, null, mediaData1) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + // THEN the event is not filtered + verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1)) + // WHEN a loaded event is received that matches the local session + filter.onMediaDataLoaded(KEY, null, mediaData2) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + // THEN the event is filtered + verify(mediaListener, never()).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData2)) + } + + @Test + fun remoteAndLocalHaveDifferentKeys_localLoadedEventFiltered() { + // GIVEN remote and local sessions + val key1 = "KEY_1" + val key2 = "KEY_2" + whenever(controller1.getPlaybackInfo()).thenReturn(remotePlaybackInfo) + val controllers = listOf(controller1, controller2) + whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers) + sessionListener.onActiveSessionsChanged(controllers) + // WHEN a loaded event is received that matches the remote session + filter.onMediaDataLoaded(key1, null, mediaData1) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + // THEN the event is not filtered + verify(mediaListener).onMediaDataLoaded(eq(key1), eq(null), eq(mediaData1)) + // WHEN a loaded event is received that matches the local session + filter.onMediaDataLoaded(key2, null, mediaData2) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + // THEN the event is filtered + verify(mediaListener, never()).onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2)) + // AND there should be a removed event for key2 + verify(mediaListener).onMediaDataRemoved(eq(key2)) + } + + @Test + fun multipleRemoteSessions_loadedEventNotFiltered() { + // GIVEN two remote sessions + whenever(controller1.getPlaybackInfo()).thenReturn(remotePlaybackInfo) + whenever(controller2.getPlaybackInfo()).thenReturn(remotePlaybackInfo) + val controllers = listOf(controller1, controller2) + whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers) + sessionListener.onActiveSessionsChanged(controllers) + // WHEN a loaded event is received that matches the remote session + filter.onMediaDataLoaded(KEY, null, mediaData1) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + // THEN the event is not filtered + verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1)) + // WHEN a loaded event is received that matches the local session + filter.onMediaDataLoaded(KEY, null, mediaData2) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + // THEN the event is not filtered + verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData2)) + } + + @Test + fun multipleOtherSessions_loadedEventNotFiltered() { + // GIVEN multiple active sessions from other packages + val controllers = listOf(controller1, controller2, controller3, controller4) + whenever(controller1.getPackageName()).thenReturn("PKG_1") + whenever(controller2.getPackageName()).thenReturn("PKG_2") + whenever(controller3.getPackageName()).thenReturn("PKG_3") + whenever(controller4.getPackageName()).thenReturn("PKG_4") + whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers) + sessionListener.onActiveSessionsChanged(controllers) + // WHEN a loaded event is received + filter.onMediaDataLoaded(KEY, null, mediaData1) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + // THEN the event is not filtered + verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1)) + } + + @Test + fun doNotFilterDuringKeyMigration() { + val key1 = "KEY_1" + val key2 = "KEY_2" + // GIVEN a loaded event + filter.onMediaDataLoaded(key1, null, mediaData2) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + reset(mediaListener) + // GIVEN remote and local sessions + whenever(controller1.getPlaybackInfo()).thenReturn(remotePlaybackInfo) + val controllers = listOf(controller1, controller2) + whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers) + sessionListener.onActiveSessionsChanged(controllers) + // WHEN a loaded event is received that matches the local session but it is a key migration + filter.onMediaDataLoaded(key2, key1, mediaData2) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + // THEN the key migration event is fired + verify(mediaListener).onMediaDataLoaded(eq(key2), eq(key1), eq(mediaData2)) + } + + @Test + fun filterAfterKeyMigration() { + val key1 = "KEY_1" + val key2 = "KEY_2" + // GIVEN a loaded event + filter.onMediaDataLoaded(key1, null, mediaData1) + filter.onMediaDataLoaded(key1, null, mediaData2) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + reset(mediaListener) + // GIVEN remote and local sessions + whenever(controller1.getPlaybackInfo()).thenReturn(remotePlaybackInfo) + val controllers = listOf(controller1, controller2) + whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers) + sessionListener.onActiveSessionsChanged(controllers) + // GIVEN that the keys have been migrated + filter.onMediaDataLoaded(key2, key1, mediaData1) + filter.onMediaDataLoaded(key2, key1, mediaData2) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + reset(mediaListener) + // WHEN a loaded event is received that matches the local session + filter.onMediaDataLoaded(key2, null, mediaData2) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + // THEN the key migration event is filtered + verify(mediaListener, never()).onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2)) + // WHEN a loaded event is received that matches the remote session + filter.onMediaDataLoaded(key2, null, mediaData1) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + // THEN the key migration event is fired + verify(mediaListener).onMediaDataLoaded(eq(key2), eq(null), eq(mediaData1)) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java index 73164b520b9d..7fabf8258198 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java @@ -54,8 +54,7 @@ public class OneHandedAnimationControllerTest extends OneHandedTestCase { MockitoAnnotations.initMocks(this); mTutorialHandler = new OneHandedTutorialHandler(mContext); - mOneHandedAnimationController = new OneHandedAnimationController( - new OneHandedSurfaceTransactionHelper(mContext)); + mOneHandedAnimationController = new OneHandedAnimationController(mContext); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java index 7d84de5caf10..95a230f6511c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java @@ -79,7 +79,7 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase { @Test public void testOneHandedManager_registerForDisplayAreaOrganizer() { - verify(mMockDisplayAreaOrganizer, times(1)).registerTransitionCallback(mGestureHandler); + verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mGestureHandler); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java index 763f6e4fe94b..d7dba5fdf8c8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java @@ -87,10 +87,8 @@ public class OneHandedManagerImplTest extends OneHandedTestCase { @Test public void testDefaultShouldNotInOneHanded() { - final OneHandedSurfaceTransactionHelper transactionHelper = - new OneHandedSurfaceTransactionHelper(mContext); final OneHandedAnimationController animationController = new OneHandedAnimationController( - transactionHelper); + mContext); OneHandedDisplayAreaOrganizer displayAreaOrganizer = new OneHandedDisplayAreaOrganizer( mContext, mMockDisplayController, animationController, mMockTutorialHandler); diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedSettingsUtilTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedSettingsUtilTest.java index f81d047b0f0c..990eb634e46f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedSettingsUtilTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedSettingsUtilTest.java @@ -40,14 +40,12 @@ import org.junit.runner.RunWith; @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper public class OneHandedSettingsUtilTest extends OneHandedTestCase { - OneHandedSettingsUtil mOneHandedSettingsUtil; ContentResolver mContentResolver; ContentObserver mContentObserver; boolean mOnChanged; @Before public void setUp() { - mOneHandedSettingsUtil = new OneHandedSettingsUtil(); mContentResolver = mContext.getContentResolver(); mContentObserver = new ContentObserver(mContext.getMainThreadHandler()) { @Override @@ -60,20 +58,20 @@ public class OneHandedSettingsUtilTest extends OneHandedTestCase { @Test public void testRegisterSecureKeyObserver() { - final Uri result = mOneHandedSettingsUtil.registerSettingsKeyObserver( + final Uri result = OneHandedSettingsUtil.registerSettingsKeyObserver( Settings.Secure.ONE_HANDED_MODE_ENABLED, mContentResolver, mContentObserver); assertThat(result).isNotNull(); - mOneHandedSettingsUtil.registerSettingsKeyObserver( + OneHandedSettingsUtil.registerSettingsKeyObserver( Settings.Secure.ONE_HANDED_MODE_ENABLED, mContentResolver, mContentObserver); } @Test public void testUnregisterSecureKeyObserver() { - mOneHandedSettingsUtil.registerSettingsKeyObserver( + OneHandedSettingsUtil.registerSettingsKeyObserver( Settings.Secure.ONE_HANDED_MODE_ENABLED, mContentResolver, mContentObserver); - mOneHandedSettingsUtil.unregisterSettingsKeyObserver(mContentResolver, mContentObserver); + OneHandedSettingsUtil.unregisterSettingsKeyObserver(mContentResolver, mContentObserver); assertThat(mOnChanged).isFalse(); @@ -85,19 +83,19 @@ public class OneHandedSettingsUtilTest extends OneHandedTestCase { @Test public void testGetSettingsIsOneHandedModeEnabled() { - assertThat(mOneHandedSettingsUtil.getSettingsOneHandedModeEnabled( + assertThat(OneHandedSettingsUtil.getSettingsOneHandedModeEnabled( mContentResolver)).isAnyOf(true, false); } @Test public void testGetSettingsTapsAppToExit() { - assertThat(mOneHandedSettingsUtil.getSettingsTapsAppToExit( + assertThat(OneHandedSettingsUtil.getSettingsTapsAppToExit( mContentResolver)).isAnyOf(true, false); } @Test public void testGetSettingsOneHandedModeTimeout() { - assertThat(mOneHandedSettingsUtil.getSettingsOneHandedModeTimeout( + assertThat(OneHandedSettingsUtil.getSettingsOneHandedModeTimeout( mContentResolver)).isAnyOf( ONE_HANDED_TIMEOUT_NEVER, ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS, @@ -107,7 +105,7 @@ public class OneHandedSettingsUtilTest extends OneHandedTestCase { @Test public void testGetSettingsSwipeToNotificationEnabled() { - assertThat(mOneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled( + assertThat(OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled( mContentResolver)).isAnyOf(true, false); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java index 8c1634e72865..8ae632dd5a47 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java @@ -77,8 +77,7 @@ public class OneHandedTouchHandlerTest extends OneHandedTestCase { @Test public void testOneHandedManager_registerForDisplayAreaOrganizer() { - verify(mMockDisplayAreaOrganizer, times(1)) - .registerTransitionCallback(mTouchHandler); + verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mTouchHandler); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java index 9e6d7976d093..c75a8d2f5454 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java @@ -16,7 +16,6 @@ package com.android.systemui.onehanded; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.testing.AndroidTestingRunner; @@ -75,7 +74,6 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase { @Test public void testOneHandedManager_registerForDisplayAreaOrganizer() { - verify(mMockDisplayAreaOrganizer, times(1)) - .registerTransitionCallback(mTutorialHandler); + verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mTutorialHandler); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java index 6db2679ea116..f0e713e42046 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java @@ -16,8 +16,7 @@ package com.android.systemui.onehanded; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.times; +import static org.junit.Assume.assumeTrue; import static org.mockito.Mockito.verify; import android.os.SystemProperties; @@ -44,7 +43,6 @@ import org.mockito.MockitoAnnotations; public class OneHandedUITest extends OneHandedTestCase { private static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode"; - boolean mIsSupportOneHandedMode; CommandQueue mCommandQueue; KeyguardUpdateMonitor mKeyguardUpdateMonitor; OneHandedUI mOneHandedUI; @@ -52,110 +50,58 @@ public class OneHandedUITest extends OneHandedTestCase { @Mock OneHandedManagerImpl mMockOneHandedManagerImpl; @Mock - OneHandedSettingsUtil mMockSettingsUtil; - @Mock OneHandedTimeoutHandler mMockTimeoutHandler; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mIsSupportOneHandedMode = SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false); mCommandQueue = new CommandQueue(mContext); mScreenLifecycle = new ScreenLifecycle(); mOneHandedUI = new OneHandedUI(mContext, mCommandQueue, mMockOneHandedManagerImpl, - mMockSettingsUtil, mScreenLifecycle); mOneHandedUI.start(); mKeyguardUpdateMonitor = mDependency.injectMockDependency(KeyguardUpdateMonitor.class); } + @Before + public void assumeOneHandedModeSupported() { + assumeTrue(SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)); + } + @Test public void testStartOneHanded() { - // Bypass test if device not support one-handed mode - if (!mIsSupportOneHandedMode) { - return; - } mOneHandedUI.startOneHanded(); - verify(mMockOneHandedManagerImpl, times(1)).startOneHanded(); + verify(mMockOneHandedManagerImpl).startOneHanded(); } @Test public void testStopOneHanded() { - // Bypass test if device not support one-handed mode - if (!mIsSupportOneHandedMode) { - return; - } mOneHandedUI.stopOneHanded(); - verify(mMockOneHandedManagerImpl, times(1)).stopOneHanded(); - } - - @Test - public void testRegisterSettingsObserver_forEnabled() { - // Bypass test if device not support one-handed mode - if (!mIsSupportOneHandedMode) { - return; - } - final String key = Settings.Secure.ONE_HANDED_MODE_ENABLED; - - verify(mMockSettingsUtil, times(1)).registerSettingsKeyObserver(key, any(), any()); - } - - @Test - public void testRegisterSettingsObserver_forTimeout() { - // Bypass test if device not support one-handed mode - if (!mIsSupportOneHandedMode) { - return; - } - final String key = Settings.Secure.ONE_HANDED_MODE_TIMEOUT; - - verify(mMockSettingsUtil, times(1)).registerSettingsKeyObserver(key, any(), any()); - } - - @Test - public void testRegisterSettingsObserver_forTapAppExit() { - // Bypass test if device not support one-handed mode - if (!mIsSupportOneHandedMode) { - return; - } - final String key = Settings.Secure.TAPS_APP_TO_EXIT; - - verify(mMockSettingsUtil, times(1)).registerSettingsKeyObserver(key, any(), any()); + verify(mMockOneHandedManagerImpl).stopOneHanded(); } @Test public void tesSettingsObserver_updateTapAppToExit() { - // Bypass test if device not support one-handed mode - if (!mIsSupportOneHandedMode) { - return; - } Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.TAPS_APP_TO_EXIT, 1); - verify(mMockOneHandedManagerImpl, times(1)).setTaskChangeToExit(true); + verify(mMockOneHandedManagerImpl).setTaskChangeToExit(true); } @Test public void tesSettingsObserver_updateEnabled() { - // Bypass test if device not support one-handed mode - if (!mIsSupportOneHandedMode) { - return; - } Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.ONE_HANDED_MODE_ENABLED, 1); - verify(mMockOneHandedManagerImpl, times(1)).setOneHandedEnabled(true); + verify(mMockOneHandedManagerImpl).setOneHandedEnabled(true); } @Test public void tesSettingsObserver_updateTimeout() { - // Bypass test if device not support one-handed mode - if (!mIsSupportOneHandedMode) { - return; - } Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.ONE_HANDED_MODE_TIMEOUT, OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS); @@ -166,10 +112,6 @@ public class OneHandedUITest extends OneHandedTestCase { @Test public void tesSettingsObserver_updateSwipeToNotification() { - // Bypass test if device not support one-handed mode - if (!mIsSupportOneHandedMode) { - return; - } Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 1); @@ -179,24 +121,16 @@ public class OneHandedUITest extends OneHandedTestCase { @Ignore("Clarifying do not receive callback") @Test public void testKeyguardBouncerShowing_shouldStopOneHanded() { - // Bypass test if device not support one-handed mode - if (!mIsSupportOneHandedMode) { - return; - } mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true); - verify(mMockOneHandedManagerImpl, times(1)).stopOneHanded(); + verify(mMockOneHandedManagerImpl).stopOneHanded(); } @Test public void testScreenTurningOff_shouldStopOneHanded() { - // Bypass test if device not support one-handed mode - if (!mIsSupportOneHandedMode) { - return; - } mScreenLifecycle.dispatchScreenTurningOff(); - verify(mMockOneHandedManagerImpl, times(1)).stopOneHanded(); + verify(mMockOneHandedManagerImpl).stopOneHanded(); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java index 9922d3620a57..b46c6ef81fa7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java @@ -152,7 +152,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { commandQueue), new InjectionInflationController( SystemUIFactory.getInstance() - .getRootComponent() + .getSysUIComponent() .createViewInstanceCreatorFactory()), mock(QSTileHost.class), mock(StatusBarStateController.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java index 184329ec6e5f..e23f92616565 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java @@ -86,7 +86,7 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase { CompletableFuture<List<Notification.Action>> smartActionsFuture = mScreenshotSmartActions.getSmartActionsFuture( "", Uri.parse("content://authority/data"), bitmap, smartActionsProvider, - true, UserHandle.getUserHandleForUid(UserHandle.myUserId())); + true, UserHandle.of(UserHandle.myUserId())); assertNotNull(smartActionsFuture); List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS); assertEquals(Collections.emptyList(), smartActions); @@ -126,7 +126,7 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase { CompletableFuture<List<Notification.Action>> smartActionsFuture = mScreenshotSmartActions.getSmartActionsFuture( "", Uri.parse("content://autority/data"), bitmap, mSmartActionsProvider, - true, UserHandle.getUserHandleForUid(UserHandle.myUserId())); + true, UserHandle.of(UserHandle.myUserId())); verify(mSmartActionsProvider, never()).getActions(any(), any(), any(), any(), any()); assertNotNull(smartActionsFuture); List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS); @@ -140,7 +140,7 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase { when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE); mScreenshotSmartActions.getSmartActionsFuture( "", Uri.parse("content://autority/data"), bitmap, mSmartActionsProvider, true, - UserHandle.getUserHandleForUid(UserHandle.myUserId())); + UserHandle.of(UserHandle.myUserId())); verify(mSmartActionsProvider, times(1)).getActions(any(), any(), any(), any(), any()); } @@ -156,7 +156,7 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase { CompletableFuture<List<Notification.Action>> smartActionsFuture = mScreenshotSmartActions.getSmartActionsFuture("", null, bitmap, actionsProvider, - true, UserHandle.getUserHandleForUid(UserHandle.myUserId())); + true, UserHandle.of(UserHandle.myUserId())); assertNotNull(smartActionsFuture); List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS); assertEquals(smartActions.size(), 0); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java index 644ed3d6e2b5..8089561f44a0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java @@ -34,7 +34,6 @@ import com.android.systemui.statusbar.notification.row.NotificationGutsManager; import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener; import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener; import com.android.systemui.statusbar.notification.stack.NotificationListContainer; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.policy.HeadsUpManager; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt index 56df1939be56..a36a4c43e278 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt @@ -29,7 +29,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.notification.ActivityLaunchAnimator import com.android.systemui.statusbar.phone.BiometricUnlockController import com.android.systemui.statusbar.phone.DozeParameters -import com.android.systemui.statusbar.phone.NotificationShadeWindowController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.mockito.eq import org.junit.Before diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java index 6f46923cda5e..1259d28c3400 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java @@ -19,12 +19,10 @@ package com.android.systemui.statusbar; import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -46,9 +44,9 @@ import com.android.systemui.statusbar.notification.DynamicChildBindController; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationActivityStarter; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.ExpandableView; @@ -212,19 +210,6 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase { } @Test - public void testUpdateNotificationViews_appOps() throws Exception { - NotificationEntry entry0 = createEntry(); - entry0.setRow(spy(entry0.getRow())); - when(mEntryManager.getVisibleNotifications()).thenReturn( - Lists.newArrayList(entry0)); - mListContainer.addContainerView(entry0.getRow()); - - mViewHierarchyManager.updateNotificationViews(); - - verify(entry0.getRow(), times(1)).showAppOpsIcons(any()); - } - - @Test public void testReentrantCallsToOnDynamicPrivacyChangedPostForLater() { // GIVEN a ListContainer that will make a re-entrant call to updateNotificationViews() mMadeReentrantCall = false; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java index ea1b498801ec..baeedcfc3fc5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java @@ -32,14 +32,17 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; -import com.android.systemui.statusbar.NotificationPresenter; +import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; @SmallTest @RunWith(AndroidTestingRunner.class) @@ -54,109 +57,126 @@ public class VisualStabilityManagerTest extends SysuiTestCase { private ExpandableNotificationRow mRow = mock(ExpandableNotificationRow.class); private NotificationEntry mEntry; + private StatusBarStateController.StateListener mStatusBarStateListener; + private WakefulnessLifecycle.Observer mWakefulnessObserver; + @Before public void setUp() { + StatusBarStateController statusBarStateController = mock(StatusBarStateController.class); + WakefulnessLifecycle wakefulnessLifecycle = mock(WakefulnessLifecycle.class); + mTestableLooper = TestableLooper.get(this); mVisualStabilityManager = new VisualStabilityManager( mock(NotificationEntryManager.class), - new Handler(mTestableLooper.getLooper())); + new Handler(mTestableLooper.getLooper()), + statusBarStateController, + wakefulnessLifecycle); - mVisualStabilityManager.setUpWithPresenter(mock(NotificationPresenter.class)); mVisualStabilityManager.setVisibilityLocationProvider(mLocationProvider); mEntry = new NotificationEntryBuilder().build(); mEntry.setRow(mRow); when(mRow.getEntry()).thenReturn(mEntry); + + ArgumentCaptor<StatusBarStateController.StateListener> stateListenerCaptor = + ArgumentCaptor.forClass(StatusBarStateController.StateListener.class); + verify(statusBarStateController).addCallback(stateListenerCaptor.capture()); + mStatusBarStateListener = stateListenerCaptor.getValue(); + + ArgumentCaptor<WakefulnessLifecycle.Observer> wakefulnessObserverCaptor = + ArgumentCaptor.forClass(WakefulnessLifecycle.Observer.class); + verify(wakefulnessLifecycle).addObserver(wakefulnessObserverCaptor.capture()); + mWakefulnessObserver = wakefulnessObserverCaptor.getValue(); } @Test public void testPanelExpansion() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); assertFalse(mVisualStabilityManager.canReorderNotification(mRow)); - mVisualStabilityManager.setPanelExpanded(false); + setPanelExpanded(false); assertTrue(mVisualStabilityManager.canReorderNotification(mRow)); } @Test public void testScreenOn() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); assertFalse(mVisualStabilityManager.canReorderNotification(mRow)); - mVisualStabilityManager.setScreenOn(false); + setScreenOn(false); assertTrue(mVisualStabilityManager.canReorderNotification(mRow)); } @Test public void testReorderingAllowedChangesScreenOn() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); assertFalse(mVisualStabilityManager.isReorderingAllowed()); - mVisualStabilityManager.setScreenOn(false); + setScreenOn(false); assertTrue(mVisualStabilityManager.isReorderingAllowed()); } @Test public void testReorderingAllowedChangesPanel() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); assertFalse(mVisualStabilityManager.isReorderingAllowed()); - mVisualStabilityManager.setPanelExpanded(false); + setPanelExpanded(false); assertTrue(mVisualStabilityManager.isReorderingAllowed()); } @Test public void testCallBackCalledScreenOn() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false /* persistent */); - mVisualStabilityManager.setScreenOn(false); + setScreenOn(false); verify(mCallback).onChangeAllowed(); } @Test public void testCallBackCalledPanelExpanded() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false /* persistent */); - mVisualStabilityManager.setPanelExpanded(false); + setPanelExpanded(false); verify(mCallback).onChangeAllowed(); } @Test public void testCallBackExactlyOnce() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false /* persistent */); - mVisualStabilityManager.setScreenOn(false); - mVisualStabilityManager.setScreenOn(true); - mVisualStabilityManager.setScreenOn(false); + setScreenOn(false); + setScreenOn(true); + setScreenOn(false); verify(mCallback).onChangeAllowed(); } @Test public void testCallBackCalledContinuouslyWhenRequested() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); mVisualStabilityManager.addReorderingAllowedCallback(mCallback, true /* persistent */); - mVisualStabilityManager.setScreenOn(false); - mVisualStabilityManager.setScreenOn(true); - mVisualStabilityManager.setScreenOn(false); + setScreenOn(false); + setScreenOn(true); + setScreenOn(false); verify(mCallback, times(2)).onChangeAllowed(); } @Test public void testAddedCanReorder() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); mVisualStabilityManager.notifyViewAddition(mRow); assertTrue(mVisualStabilityManager.canReorderNotification(mRow)); } @Test public void testReorderingVisibleHeadsUpNotAllowed() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); when(mLocationProvider.isInVisibleLocation(any(NotificationEntry.class))).thenReturn(true); mVisualStabilityManager.onHeadsUpStateChanged(mEntry, true); assertFalse(mVisualStabilityManager.canReorderNotification(mRow)); @@ -164,8 +184,8 @@ public class VisualStabilityManagerTest extends SysuiTestCase { @Test public void testReorderingVisibleHeadsUpAllowed() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); when(mLocationProvider.isInVisibleLocation(any(NotificationEntry.class))).thenReturn(false); mVisualStabilityManager.onHeadsUpStateChanged(mEntry, true); assertTrue(mVisualStabilityManager.canReorderNotification(mRow)); @@ -173,8 +193,8 @@ public class VisualStabilityManagerTest extends SysuiTestCase { @Test public void testReorderingVisibleHeadsUpAllowedOnce() { - mVisualStabilityManager.setPanelExpanded(true); - mVisualStabilityManager.setScreenOn(true); + setPanelExpanded(true); + setScreenOn(true); when(mLocationProvider.isInVisibleLocation(any(NotificationEntry.class))).thenReturn(false); mVisualStabilityManager.onHeadsUpStateChanged(mEntry, true); mVisualStabilityManager.onReorderingFinished(); @@ -183,33 +203,33 @@ public class VisualStabilityManagerTest extends SysuiTestCase { @Test public void testPulsing() { - mVisualStabilityManager.setPulsing(true); + setPulsing(true); assertFalse(mVisualStabilityManager.canReorderNotification(mRow)); - mVisualStabilityManager.setPulsing(false); + setPulsing(false); assertTrue(mVisualStabilityManager.canReorderNotification(mRow)); } @Test public void testReorderingAllowedChanges_Pulsing() { - mVisualStabilityManager.setPulsing(true); + setPulsing(true); assertFalse(mVisualStabilityManager.isReorderingAllowed()); - mVisualStabilityManager.setPulsing(false); + setPulsing(false); assertTrue(mVisualStabilityManager.isReorderingAllowed()); } @Test public void testCallBackCalled_Pulsing() { - mVisualStabilityManager.setPulsing(true); + setPulsing(true); mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false /* persistent */); - mVisualStabilityManager.setPulsing(false); + setPulsing(false); verify(mCallback).onChangeAllowed(); } @Test public void testTemporarilyAllowReorderingNotifiesCallbacks() { // GIVEN having the panel open (which would block reordering) - mVisualStabilityManager.setScreenOn(true); - mVisualStabilityManager.setPanelExpanded(true); + setScreenOn(true); + setPanelExpanded(true); mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false /* persistent */); // WHEN we temprarily allow reordering @@ -223,7 +243,7 @@ public class VisualStabilityManagerTest extends SysuiTestCase { @Test public void testTemporarilyAllowReorderingDoesntOverridePulsing() { // GIVEN we are in a pulsing state - mVisualStabilityManager.setPulsing(true); + setPulsing(true); mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false /* persistent */); // WHEN we temprarily allow reordering @@ -237,8 +257,8 @@ public class VisualStabilityManagerTest extends SysuiTestCase { @Test public void testTemporarilyAllowReorderingExpires() { // GIVEN having the panel open (which would block reordering) - mVisualStabilityManager.setScreenOn(true); - mVisualStabilityManager.setPanelExpanded(true); + setScreenOn(true); + setPanelExpanded(true); mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false /* persistent */); // WHEN we temprarily allow reordering and then wait until the window expires @@ -249,4 +269,20 @@ public class VisualStabilityManagerTest extends SysuiTestCase { // THEN reordering is no longer allowed assertFalse(mVisualStabilityManager.isReorderingAllowed()); } + + private void setPanelExpanded(boolean expanded) { + mStatusBarStateListener.onExpandedChanged(expanded); + } + + private void setPulsing(boolean pulsing) { + mStatusBarStateListener.onPulsingChanged(pulsing); + } + + private void setScreenOn(boolean screenOn) { + if (screenOn) { + mWakefulnessObserver.onStartedWakingUp(); + } else { + mWakefulnessObserver.onFinishedGoingToSleep(); + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java index 960ea79f36b4..ce8ce2e39bcc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java @@ -77,8 +77,6 @@ public class AppOpsCoordinatorTest extends SysuiTestCase { private NotificationEntryBuilder mEntryBuilder; private AppOpsCoordinator mAppOpsCoordinator; private NotifFilter mForegroundFilter; - private NotifCollectionListener mNotifCollectionListener; - private AppOpsController.Callback mAppOpsCallback; private NotifLifetimeExtender mForegroundNotifLifetimeExtender; private NotifSection mFgsSection; @@ -113,19 +111,6 @@ public class AppOpsCoordinatorTest extends SysuiTestCase { lifetimeExtenderCaptor.capture()); mForegroundNotifLifetimeExtender = lifetimeExtenderCaptor.getValue(); - // capture notifCollectionListener - ArgumentCaptor<NotifCollectionListener> notifCollectionCaptor = - ArgumentCaptor.forClass(NotifCollectionListener.class); - verify(mNotifPipeline, times(1)).addCollectionListener( - notifCollectionCaptor.capture()); - mNotifCollectionListener = notifCollectionCaptor.getValue(); - - // capture app ops callback - ArgumentCaptor<AppOpsController.Callback> appOpsCaptor = - ArgumentCaptor.forClass(AppOpsController.Callback.class); - verify(mAppOpsController).addCallback(any(int[].class), appOpsCaptor.capture()); - mAppOpsCallback = appOpsCaptor.getValue(); - mFgsSection = mAppOpsCoordinator.getSection(); } @@ -230,136 +215,6 @@ public class AppOpsCoordinatorTest extends SysuiTestCase { } @Test - public void testAppOpsUpdateOnlyAppliedToRelevantNotificationWithStandardLayout() { - // GIVEN three current notifications, two with the same key but from different users - NotificationEntry entry1 = new NotificationEntryBuilder() - .setUser(new UserHandle(NOTIF_USER_ID)) - .setPkg(TEST_PKG) - .setId(1) - .build(); - NotificationEntry entry2 = new NotificationEntryBuilder() - .setUser(new UserHandle(NOTIF_USER_ID)) - .setPkg(TEST_PKG) - .setId(2) - .build(); - NotificationEntry entry3_diffUser = new NotificationEntryBuilder() - .setUser(new UserHandle(NOTIF_USER_ID + 1)) - .setPkg(TEST_PKG) - .setId(2) - .build(); - when(mNotifPipeline.getAllNotifs()).thenReturn(List.of(entry1, entry2, entry3_diffUser)); - - // GIVEN that only entry2 has a standard layout - when(mForegroundServiceController.getStandardLayoutKeys(NOTIF_USER_ID, TEST_PKG)) - .thenReturn(new ArraySet<>(List.of(entry2.getKey()))); - - // WHEN a new app ops code comes in - mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, true); - mExecutor.runAllReady(); - - // THEN entry2's app ops are updated, but no one else's are - assertEquals( - new ArraySet<>(), - entry1.mActiveAppOps); - assertEquals( - new ArraySet<>(List.of(47)), - entry2.mActiveAppOps); - assertEquals( - new ArraySet<>(), - entry3_diffUser.mActiveAppOps); - } - - @Test - public void testAppOpsUpdateAppliedToAllNotificationsWithStandardLayouts() { - // GIVEN three notifications with standard layouts - NotificationEntry entry1 = new NotificationEntryBuilder() - .setUser(new UserHandle(NOTIF_USER_ID)) - .setPkg(TEST_PKG) - .setId(1) - .build(); - NotificationEntry entry2 = new NotificationEntryBuilder() - .setUser(new UserHandle(NOTIF_USER_ID)) - .setPkg(TEST_PKG) - .setId(2) - .build(); - NotificationEntry entry3 = new NotificationEntryBuilder() - .setUser(new UserHandle(NOTIF_USER_ID)) - .setPkg(TEST_PKG) - .setId(3) - .build(); - when(mNotifPipeline.getAllNotifs()).thenReturn(List.of(entry1, entry2, entry3)); - when(mForegroundServiceController.getStandardLayoutKeys(NOTIF_USER_ID, TEST_PKG)) - .thenReturn(new ArraySet<>(List.of(entry1.getKey(), entry2.getKey(), - entry3.getKey()))); - - // WHEN a new app ops code comes in - mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, true); - mExecutor.runAllReady(); - - // THEN all entries get updated - assertEquals( - new ArraySet<>(List.of(47)), - entry1.mActiveAppOps); - assertEquals( - new ArraySet<>(List.of(47)), - entry2.mActiveAppOps); - assertEquals( - new ArraySet<>(List.of(47)), - entry3.mActiveAppOps); - } - - @Test - public void testAppOpsAreRemoved() { - // GIVEN One notification which is associated with app ops - NotificationEntry entry = new NotificationEntryBuilder() - .setUser(new UserHandle(NOTIF_USER_ID)) - .setPkg(TEST_PKG) - .setId(2) - .build(); - when(mNotifPipeline.getAllNotifs()).thenReturn(List.of(entry)); - when(mForegroundServiceController.getStandardLayoutKeys(0, TEST_PKG)) - .thenReturn(new ArraySet<>(List.of(entry.getKey()))); - - // GIVEN that the notification's app ops are already [47, 33] - mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, true); - mAppOpsCallback.onActiveStateChanged(33, NOTIF_USER_ID, TEST_PKG, true); - mExecutor.runAllReady(); - assertEquals( - new ArraySet<>(List.of(47, 33)), - entry.mActiveAppOps); - - // WHEN one of the app ops is removed - mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, false); - mExecutor.runAllReady(); - - // THEN the entry's active app ops are updated as well - assertEquals( - new ArraySet<>(List.of(33)), - entry.mActiveAppOps); - } - - @Test - public void testNullAppOps() { - // GIVEN one notification with app ops - NotificationEntry entry = new NotificationEntryBuilder() - .setUser(new UserHandle(NOTIF_USER_ID)) - .setPkg(TEST_PKG) - .setId(2) - .build(); - entry.mActiveAppOps.clear(); - entry.mActiveAppOps.addAll(List.of(47, 33)); - - // WHEN the notification is updated and the foreground service controller returns null for - // this notification - when(mForegroundServiceController.getAppOps(entry.getSbn().getUser().getIdentifier(), - entry.getSbn().getPackageName())).thenReturn(null); - mNotifCollectionListener.onEntryUpdated(entry); - - // THEN the entry's active app ops is updated to empty - assertTrue(entry.mActiveAppOps.isEmpty()); - } - - @Test public void testIncludeFGSInSection_importanceDefault() { // GIVEN the notification represents a colorized foreground service with > min importance mEntryBuilder diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java new file mode 100644 index 000000000000..605b4d18d2f1 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java @@ -0,0 +1,341 @@ +/* + * 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.collection.coordinator; + +import static junit.framework.Assert.assertFalse; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.notification.collection.NotifPipeline; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager; +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable; +import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; +import com.android.systemui.statusbar.policy.HeadsUpManager; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.time.FakeSystemClock; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class VisualStabilityCoordinatorTest extends SysuiTestCase { + + private VisualStabilityCoordinator mCoordinator; + + // captured listeners and pluggables: + private NotifCollectionListener mCollectionListener; + + @Mock private NotifPipeline mNotifPipeline; + @Mock private WakefulnessLifecycle mWakefulnessLifecycle; + @Mock private StatusBarStateController mStatusBarStateController; + @Mock private Pluggable.PluggableListener<NotifStabilityManager> mInvalidateListener; + @Mock private HeadsUpManager mHeadsUpManager; + + @Captor private ArgumentCaptor<WakefulnessLifecycle.Observer> mWakefulnessObserverCaptor; + @Captor private ArgumentCaptor<StatusBarStateController.StateListener> mSBStateListenerCaptor; + @Captor private ArgumentCaptor<NotifStabilityManager> mNotifStabilityManagerCaptor; + @Captor private ArgumentCaptor<NotifCollectionListener> mNotifCollectionListenerCaptor; + + private FakeSystemClock mFakeSystemClock = new FakeSystemClock(); + private FakeExecutor mFakeExecutor = new FakeExecutor(mFakeSystemClock); + + private WakefulnessLifecycle.Observer mWakefulnessObserver; + private StatusBarStateController.StateListener mStatusBarStateListener; + private NotifStabilityManager mNotifStabilityManager; + private NotificationEntry mEntry; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mCoordinator = new VisualStabilityCoordinator( + mHeadsUpManager, + mWakefulnessLifecycle, + mStatusBarStateController, + mFakeExecutor); + + mCoordinator.attach(mNotifPipeline); + + // capture arguments: + verify(mWakefulnessLifecycle).addObserver(mWakefulnessObserverCaptor.capture()); + mWakefulnessObserver = mWakefulnessObserverCaptor.getValue(); + + verify(mStatusBarStateController).addCallback(mSBStateListenerCaptor.capture()); + mStatusBarStateListener = mSBStateListenerCaptor.getValue(); + + verify(mNotifPipeline).setVisualStabilityManager(mNotifStabilityManagerCaptor.capture()); + mNotifStabilityManager = mNotifStabilityManagerCaptor.getValue(); + mNotifStabilityManager.setInvalidationListener(mInvalidateListener); + + mEntry = new NotificationEntryBuilder() + .setPkg("testPkg1") + .build(); + + when(mHeadsUpManager.isAlerting(mEntry.getKey())).thenReturn(false); + } + + @Test + public void testScreenOff_groupAndSectionChangesAllowed() { + // GIVEN screen is off, panel isn't expanded and device isn't pulsing + setScreenOn(false); + setPanelExpanded(false); + setPulsing(false); + + // THEN group changes are allowed + assertTrue(mNotifStabilityManager.isGroupChangeAllowed(mEntry)); + + // THEN section changes are allowed + assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + } + + @Test + public void testPanelNotExpanded_groupAndSectionChangesAllowed() { + // GIVEN screen is on but the panel isn't expanded and device isn't pulsing + setScreenOn(true); + setPanelExpanded(false); + setPulsing(false); + + // THEN group changes are allowed + assertTrue(mNotifStabilityManager.isGroupChangeAllowed(mEntry)); + + // THEN section changes are allowed + assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + } + + @Test + public void testPanelExpanded_groupAndSectionChangesNotAllowed() { + // GIVEN the panel true expanded and device isn't pulsing + setScreenOn(true); + setPanelExpanded(true); + setPulsing(false); + + // THEN group changes are NOT allowed + assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry)); + + // THEN section changes are NOT allowed + assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + } + + @Test + public void testPulsing_screenOff_groupAndSectionChangesNotAllowed() { + // GIVEN the device is pulsing and screen is off + setScreenOn(false); + setPulsing(true); + + // THEN group changes are NOT allowed + assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry)); + + // THEN section changes are NOT allowed + assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + } + + @Test + public void testPulsing_panelNotExpanded_groupAndSectionChangesNotAllowed() { + // GIVEN the device is pulsing and screen is off with the panel not expanded + setScreenOn(false); + setPanelExpanded(false); + setPulsing(true); + + // THEN group changes are NOT allowed + assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry)); + + // THEN section changes are NOT allowed + assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + } + + @Test + public void testOverrideReorderingSuppression_onlySectionChangesAllowed() { + // GIVEN section changes typically wouldn't be allowed because the panel is expanded and + // we're not pulsing + setScreenOn(true); + setPanelExpanded(true); + setPulsing(true); + + // WHEN we temporarily allow section changes for this notification entry + mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.currentTimeMillis()); + + // THEN group changes aren't allowed + assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry)); + + // THEN section changes are allowed for this notification but not other notifications + assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + assertFalse(mNotifStabilityManager.isSectionChangeAllowed( + new NotificationEntryBuilder() + .setPkg("testPkg2") + .build())); + } + + @Test + public void testTemporarilyAllowSectionChanges_callsInvalidate() { + // GIVEN section changes typically wouldn't be allowed because the panel is expanded + setScreenOn(true); + setPanelExpanded(true); + setPulsing(false); + + // WHEN we temporarily allow section changes for this notification entry + mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.uptimeMillis()); + + // THEN the notification list is invalidated + verifyInvalidateCalled(true); + } + + @Test + public void testTemporarilyAllowSectionChanges_noInvalidationCalled() { + // GIVEN section changes typically WOULD be allowed + setScreenOn(false); + setPanelExpanded(false); + setPulsing(false); + + // WHEN we temporarily allow section changes for this notification entry + mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.currentTimeMillis()); + + // THEN invalidate is not called because this entry was never suppressed from reordering + verifyInvalidateCalled(false); + } + + @Test + public void testTemporarilyAllowSectionChangesTimeout() { + // GIVEN section changes typically WOULD be allowed + setScreenOn(false); + setPanelExpanded(false); + setPulsing(false); + assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + + // WHEN we temporarily allow section changes for this notification entry + mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.currentTimeMillis()); + + // THEN invalidate is not called because this entry was never suppressed from reordering; + // THEN section changes are allowed for this notification + verifyInvalidateCalled(false); + assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + + // WHEN we're pulsing (now disallowing reordering) + setPulsing(true); + + // THEN we're still allowed to reorder this section because it's still in the list of + // notifications to allow section changes + assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + + // WHEN the timeout for the temporarily allow section reordering runnable is finsihed + mFakeExecutor.advanceClockToNext(); + mFakeExecutor.runNextReady(); + + // THEN section changes aren't allowed anymore + assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + } + + @Test + public void testTemporarilyAllowSectionChanges_isPulsingChangeBeforeTimeout() { + // GIVEN section changes typically wouldn't be allowed because the device is pulsing + setScreenOn(false); + setPanelExpanded(false); + setPulsing(true); + + // WHEN we temporarily allow section changes for this notification entry + mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.currentTimeMillis()); + verifyInvalidateCalled(true); // can now reorder, so invalidates + + // WHEN reordering is now allowed because device isn't pulsing anymore + setPulsing(false); + + // THEN invalidate isn't called since reordering was already allowed + verifyInvalidateCalled(false); + } + + @Test + public void testNeverSuppressedChanges_noInvalidationCalled() { + // GIVEN no notifications are currently being suppressed from grouping nor being sorted + + // WHEN device isn't pulsing anymore + setPulsing(false); + + // WHEN screen isn't on + setScreenOn(false); + + // WHEN panel isn't expanded + setPanelExpanded(false); + + // THEN we never see any calls to invalidate since there weren't any notifications that + // were being suppressed from grouping or section changes + verifyInvalidateCalled(false); + } + + @Test + public void testHeadsUp_allowedToChangeGroupAndSection() { + // GIVEN group + section changes disallowed + setScreenOn(true); + setPanelExpanded(true); + setPulsing(true); + assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry)); + assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + + // GIVEN mEntry is a HUN + when(mHeadsUpManager.isAlerting(mEntry.getKey())).thenReturn(true); + + // THEN group + section changes are allowed + assertTrue(mNotifStabilityManager.isGroupChangeAllowed(mEntry)); + assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry)); + + } + + private void setPulsing(boolean pulsing) { + mStatusBarStateListener.onPulsingChanged(pulsing); + } + + private void setScreenOn(boolean screenOn) { + if (screenOn) { + mWakefulnessObserver.onStartedWakingUp(); + } else { + mWakefulnessObserver.onFinishedGoingToSleep(); + } + } + + private void setPanelExpanded(boolean expanded) { + mStatusBarStateListener.onExpandedChanged(expanded); + } + + private void verifyInvalidateCalled(boolean invalidateCalled) { + if (invalidateCalled) { + verify(mInvalidateListener).onPluggableInvalidated(mNotifStabilityManager); + } else { + verify(mInvalidateListener, never()).onPluggableInvalidated(mNotifStabilityManager); + } + + reset(mInvalidateListener); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java deleted file mode 100644 index 43d8b50bcf72..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java +++ /dev/null @@ -1,230 +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.systemui.statusbar.notification.row; - -import static android.app.AppOpsManager.OP_CAMERA; -import static android.app.AppOpsManager.OP_RECORD_AUDIO; -import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertTrue; - -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyBoolean; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.Notification; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.graphics.drawable.Drawable; -import android.os.UserHandle; -import android.service.notification.StatusBarNotification; -import android.test.suitebuilder.annotation.SmallTest; -import android.testing.AndroidTestingRunner; -import android.testing.UiThreadTest; -import android.util.ArraySet; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; - -import com.android.internal.logging.testing.UiEventLoggerFake; -import com.android.systemui.R; -import com.android.systemui.SysuiTestCase; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.concurrent.CountDownLatch; - -@SmallTest -@RunWith(AndroidTestingRunner.class) -@UiThreadTest -public class AppOpsInfoTest extends SysuiTestCase { - private static final String TEST_PACKAGE_NAME = "test_package"; - private static final int TEST_UID = 1; - - private AppOpsInfo mAppOpsInfo; - private final PackageManager mMockPackageManager = mock(PackageManager.class); - private final NotificationGuts mGutsParent = mock(NotificationGuts.class); - private StatusBarNotification mSbn; - private UiEventLoggerFake mUiEventLogger = new UiEventLoggerFake(); - - @Before - public void setUp() throws Exception { - // Inflate the layout - final LayoutInflater layoutInflater = LayoutInflater.from(mContext); - mAppOpsInfo = (AppOpsInfo) layoutInflater.inflate(R.layout.app_ops_info, null); - mAppOpsInfo.setGutsParent(mGutsParent); - - // PackageManager must return a packageInfo and applicationInfo. - final PackageInfo packageInfo = new PackageInfo(); - packageInfo.packageName = TEST_PACKAGE_NAME; - when(mMockPackageManager.getPackageInfo(eq(TEST_PACKAGE_NAME), anyInt())) - .thenReturn(packageInfo); - final ApplicationInfo applicationInfo = new ApplicationInfo(); - applicationInfo.uid = TEST_UID; // non-zero - when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn( - applicationInfo); - - mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, - new Notification(), UserHandle.CURRENT, null, 0); - } - - @Test - public void testBindNotification_SetsTextApplicationName() { - when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name"); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, new ArraySet<>()); - final TextView textView = mAppOpsInfo.findViewById(R.id.pkgname); - assertTrue(textView.getText().toString().contains("App Name")); - } - - @Test - public void testBindNotification_SetsPackageIcon() { - final Drawable iconDrawable = mock(Drawable.class); - when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class))) - .thenReturn(iconDrawable); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, new ArraySet<>()); - final ImageView iconView = mAppOpsInfo.findViewById(R.id.pkgicon); - assertEquals(iconDrawable, iconView.getDrawable()); - } - - @Test - public void testBindNotification_SetsOnClickListenerForSettings() throws Exception { - ArraySet<Integer> expectedOps = new ArraySet<>(); - expectedOps.add(OP_CAMERA); - final CountDownLatch latch = new CountDownLatch(1); - mAppOpsInfo.bindGuts(mMockPackageManager, (View v, String pkg, int uid, - ArraySet<Integer> ops) -> { - assertEquals(TEST_PACKAGE_NAME, pkg); - assertEquals(expectedOps, ops); - assertEquals(TEST_UID, uid); - latch.countDown(); - }, mSbn, mUiEventLogger, expectedOps); - - final View settingsButton = mAppOpsInfo.findViewById(R.id.settings); - settingsButton.performClick(); - // Verify that listener was triggered. - assertEquals(0, latch.getCount()); - } - - @Test - public void testBindNotification_LogsOpen() throws Exception { - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, new ArraySet<>()); - assertEquals(1, mUiEventLogger.numLogs()); - assertEquals(NotificationAppOpsEvent.NOTIFICATION_APP_OPS_OPEN.getId(), - mUiEventLogger.eventId(0)); - } - - @Test - public void testOk() { - ArraySet<Integer> expectedOps = new ArraySet<>(); - expectedOps.add(OP_CAMERA); - final CountDownLatch latch = new CountDownLatch(1); - mAppOpsInfo.bindGuts(mMockPackageManager, (View v, String pkg, int uid, - ArraySet<Integer> ops) -> { - assertEquals(TEST_PACKAGE_NAME, pkg); - assertEquals(expectedOps, ops); - assertEquals(TEST_UID, uid); - latch.countDown(); - }, mSbn, mUiEventLogger, expectedOps); - - final View okButton = mAppOpsInfo.findViewById(R.id.ok); - okButton.performClick(); - assertEquals(1, latch.getCount()); - verify(mGutsParent, times(1)).closeControls(eq(okButton), anyBoolean()); - } - - @Test - public void testPrompt_camera() { - ArraySet<Integer> expectedOps = new ArraySet<>(); - expectedOps.add(OP_CAMERA); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); - TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); - assertEquals("This app is using the camera.", prompt.getText()); - } - - @Test - public void testPrompt_mic() { - ArraySet<Integer> expectedOps = new ArraySet<>(); - expectedOps.add(OP_RECORD_AUDIO); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); - TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); - assertEquals("This app is using the microphone.", prompt.getText()); - } - - @Test - public void testPrompt_overlay() { - ArraySet<Integer> expectedOps = new ArraySet<>(); - expectedOps.add(OP_SYSTEM_ALERT_WINDOW); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); - TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); - assertEquals("This app is displaying over other apps on your screen.", prompt.getText()); - } - - @Test - public void testPrompt_camera_mic() { - ArraySet<Integer> expectedOps = new ArraySet<>(); - expectedOps.add(OP_CAMERA); - expectedOps.add(OP_RECORD_AUDIO); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); - TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); - assertEquals("This app is using the microphone and camera.", prompt.getText()); - } - - @Test - public void testPrompt_camera_mic_overlay() { - ArraySet<Integer> expectedOps = new ArraySet<>(); - expectedOps.add(OP_CAMERA); - expectedOps.add(OP_RECORD_AUDIO); - expectedOps.add(OP_SYSTEM_ALERT_WINDOW); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); - TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); - assertEquals("This app is displaying over other apps on your screen and using" - + " the microphone and camera.", prompt.getText()); - } - - @Test - public void testPrompt_camera_overlay() { - ArraySet<Integer> expectedOps = new ArraySet<>(); - expectedOps.add(OP_CAMERA); - expectedOps.add(OP_SYSTEM_ALERT_WINDOW); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); - TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); - assertEquals("This app is displaying over other apps on your screen and using" - + " the camera.", prompt.getText()); - } - - @Test - public void testPrompt_mic_overlay() { - ArraySet<Integer> expectedOps = new ArraySet<>(); - expectedOps.add(OP_RECORD_AUDIO); - expectedOps.add(OP_SYSTEM_ALERT_WINDOW); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); - TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); - assertEquals("This app is displaying over other apps on your screen and using" - + " the microphone.", prompt.getText()); - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java index dc4a6ca14a77..f29b46c73e4d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java @@ -35,12 +35,10 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.app.AppOpsManager; import android.app.NotificationChannel; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; -import android.util.ArraySet; import android.view.View; import androidx.test.filters.SmallTest; @@ -213,46 +211,6 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { } @Test - public void testShowAppOps_noHeader() { - // public notification is custom layout - no header - mGroupRow.setSensitive(true, true); - mGroupRow.setAppOpsOnClickListener(null); - mGroupRow.showAppOpsIcons(null); - } - - @Test - public void testShowAppOpsIcons_header() { - NotificationContentView publicLayout = mock(NotificationContentView.class); - mGroupRow.setPublicLayout(publicLayout); - NotificationContentView privateLayout = mock(NotificationContentView.class); - mGroupRow.setPrivateLayout(privateLayout); - NotificationChildrenContainer mockContainer = mock(NotificationChildrenContainer.class); - when(mockContainer.getNotificationChildCount()).thenReturn(1); - mGroupRow.setChildrenContainer(mockContainer); - - ArraySet<Integer> ops = new ArraySet<>(); - ops.add(AppOpsManager.OP_ANSWER_PHONE_CALLS); - mGroupRow.showAppOpsIcons(ops); - - verify(mockContainer, times(1)).showAppOpsIcons(ops); - verify(privateLayout, times(1)).showAppOpsIcons(ops); - verify(publicLayout, times(1)).showAppOpsIcons(ops); - - } - - @Test - public void testAppOpsOnClick() { - ExpandableNotificationRow.CoordinateOnClickListener l = mock( - ExpandableNotificationRow.CoordinateOnClickListener.class); - View view = mock(View.class); - - mGroupRow.setAppOpsOnClickListener(l); - - mGroupRow.getAppOpsOnClickListener().onClick(view); - verify(l, times(1)).onClick(any(), anyInt(), anyInt(), any()); - } - - @Test public void testFeedback_noHeader() { // public notification is custom layout - no header mGroupRow.setSensitive(true, true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java index 6d4a7115b8c4..c2091da2347e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java @@ -76,32 +76,6 @@ public class NotificationContentViewTest extends SysuiTestCase { @Test @UiThreadTest - public void testShowAppOpsIcons() { - View mockContracted = mock(NotificationHeaderView.class); - when(mockContracted.findViewById(com.android.internal.R.id.mic)) - .thenReturn(mockContracted); - View mockExpanded = mock(NotificationHeaderView.class); - when(mockExpanded.findViewById(com.android.internal.R.id.mic)) - .thenReturn(mockExpanded); - View mockHeadsUp = mock(NotificationHeaderView.class); - when(mockHeadsUp.findViewById(com.android.internal.R.id.mic)) - .thenReturn(mockHeadsUp); - - mView.setContractedChild(mockContracted); - mView.setExpandedChild(mockExpanded); - mView.setHeadsUpChild(mockHeadsUp); - - ArraySet<Integer> ops = new ArraySet<>(); - ops.add(AppOpsManager.OP_RECORD_AUDIO); - mView.showAppOpsIcons(ops); - - verify(mockContracted, times(1)).setVisibility(View.VISIBLE); - verify(mockExpanded, times(1)).setVisibility(View.VISIBLE); - verify(mockHeadsUp, times(1)).setVisibility(View.VISIBLE); - } - - @Test - @UiThreadTest public void testShowFeedbackIcon() { View mockContracted = mock(NotificationHeaderView.class); when(mockContracted.findViewById(com.android.internal.R.id.feedback)) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java index 83fc82634b60..3c5aa1ae9519 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java @@ -79,7 +79,6 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.bubbles.BubblesTestActivity; import com.android.systemui.statusbar.SbnBuilder; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.statusbar.phone.ShadeController; @@ -135,7 +134,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { @Mock private PackageManager mMockPackageManager; @Mock - private VisualStabilityManager mVisualStabilityManager; + private OnUserInteractionCallback mOnUserInteractionCallback; @Mock private BubbleController mBubbleController; @Mock @@ -244,7 +243,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -268,7 +267,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -293,7 +292,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mLauncherApps, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -319,7 +318,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -344,7 +343,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -368,7 +367,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -403,7 +402,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, entry, @@ -428,7 +427,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -457,7 +456,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -481,7 +480,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -509,7 +508,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -537,7 +536,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -568,7 +567,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -598,7 +597,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -642,7 +641,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -685,7 +684,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -729,7 +728,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -766,7 +765,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -802,7 +801,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -840,7 +839,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -876,7 +875,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -912,7 +911,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -947,7 +946,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -981,7 +980,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -1006,7 +1005,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -1041,7 +1040,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, @@ -1081,7 +1080,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mShortcutManager, mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, TEST_PACKAGE_NAME, mNotificationChannel, mEntry, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java index 54ccc4d8320d..c2c40cac3d0f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java @@ -74,7 +74,6 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.notification.AssistantFeedbackController; import com.android.systemui.statusbar.notification.NotificationActivityStarter; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; @@ -114,7 +113,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase { @Rule public MockitoRule mockito = MockitoJUnit.rule(); @Mock private MetricsLogger mMetricsLogger; - @Mock private VisualStabilityManager mVisualStabilityManager; + @Mock private OnUserInteractionCallback mOnUserInteractionCallback; @Mock private NotificationPresenter mPresenter; @Mock private NotificationActivityStarter mNotificationActivityStarter; @Mock private NotificationListContainer mNotificationListContainer; @@ -143,19 +142,21 @@ public class NotificationGutsManagerTest extends SysuiTestCase { mDependency.injectTestDependency(DeviceProvisionedController.class, mDeviceProvisionedController); mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger); - mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager); + mDependency.injectTestDependency( + OnUserInteractionCallback.class, + mOnUserInteractionCallback); mDependency.injectTestDependency(BubbleController.class, mBubbleController); mDependency.injectMockDependency(NotificationLockscreenUserManager.class); mHandler = Handler.createAsync(mTestableLooper.getLooper()); mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this)); when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false); - mGutsManager = new NotificationGutsManager(mContext, mVisualStabilityManager, + mGutsManager = new NotificationGutsManager(mContext, () -> mStatusBar, mHandler, mHandler, mAccessibilityManager, mHighPriorityProvider, mINotificationManager, mLauncherApps, mShortcutManager, mChannelEditorDialogController, mContextTracker, mProvider, mAssistantFeedbackController, mBubbleController, - new UiEventLoggerFake()); + new UiEventLoggerFake(), mOnUserInteractionCallback); mGutsManager.setUpWithPresenter(mPresenter, mNotificationListContainer, mCheckSaveListener, mOnSettingsClickListener); mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter); @@ -360,7 +361,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase { verify(notificationInfoView).bindNotification( any(PackageManager.class), any(INotificationManager.class), - eq(mVisualStabilityManager), + eq(mOnUserInteractionCallback), eq(mChannelEditorDialogController), eq(statusBarNotification.getPackageName()), any(NotificationChannel.class), @@ -394,7 +395,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase { verify(notificationInfoView).bindNotification( any(PackageManager.class), any(INotificationManager.class), - eq(mVisualStabilityManager), + eq(mOnUserInteractionCallback), eq(mChannelEditorDialogController), eq(statusBarNotification.getPackageName()), any(NotificationChannel.class), @@ -426,7 +427,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase { verify(notificationInfoView).bindNotification( any(PackageManager.class), any(INotificationManager.class), - eq(mVisualStabilityManager), + eq(mOnUserInteractionCallback), eq(mChannelEditorDialogController), eq(statusBarNotification.getPackageName()), any(NotificationChannel.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java index fd8b72bb15db..02a3e11f312b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java @@ -66,7 +66,6 @@ import com.android.internal.logging.testing.UiEventLoggerFake; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; @@ -114,7 +113,7 @@ public class NotificationInfoTest extends SysuiTestCase { @Mock private PackageManager mMockPackageManager; @Mock - private VisualStabilityManager mVisualStabilityManager; + private OnUserInteractionCallback mOnUserInteractionCallback; @Mock private ChannelEditorDialogController mChannelEditorDialogController; @@ -181,7 +180,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -207,7 +206,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -229,7 +228,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -260,7 +259,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -283,7 +282,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -311,7 +310,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -334,7 +333,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -356,7 +355,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mDefaultNotificationChannel, @@ -382,7 +381,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mDefaultNotificationChannel, @@ -404,7 +403,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -427,7 +426,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -455,7 +454,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -478,7 +477,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -502,7 +501,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -518,7 +517,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -541,7 +540,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, createMultipleChannelSet(MULTIPLE_CHANNEL_COUNT), @@ -569,7 +568,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -593,7 +592,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -617,7 +616,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -643,7 +642,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -665,7 +664,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -688,7 +687,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -709,7 +708,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -730,7 +729,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -751,7 +750,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -774,7 +773,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -798,7 +797,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -825,7 +824,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -852,7 +851,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -879,7 +878,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -914,7 +913,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -942,7 +941,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -982,7 +981,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1017,7 +1016,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1047,7 +1046,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1082,7 +1081,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1120,7 +1119,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1157,7 +1156,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1175,7 +1174,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.findViewById(R.id.done).performClick(); mNotificationInfo.handleCloseControls(true, false); - verify(mVisualStabilityManager).temporarilyAllowReordering(); + verify(mOnUserInteractionCallback).onImportanceChanged(mEntry); } @Test @@ -1185,7 +1184,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1216,7 +1215,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1250,7 +1249,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1283,7 +1282,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1316,7 +1315,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, @@ -1342,7 +1341,7 @@ public class NotificationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, - mVisualStabilityManager, + mOnUserInteractionCallback, mChannelEditorDialogController, TEST_PACKAGE_NAME, mNotificationChannel, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java index 8ccbb2ebb0db..9a8678f01870 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java @@ -52,6 +52,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationRemoteInputManager; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.notification.ConversationNotificationProcessor; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -68,7 +69,6 @@ import com.android.systemui.statusbar.phone.ConfigurationControllerImpl; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.NotificationGroupManager; -import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.policy.SmartReplyConstants; import org.mockito.ArgumentCaptor; @@ -422,10 +422,10 @@ public class NotificationTestHelper { mock(OnExpandClickListener.class), mock(NotificationMediaManager.class), mock(ExpandableNotificationRow.CoordinateOnClickListener.class), - mock(ExpandableNotificationRow.CoordinateOnClickListener.class), mock(FalsingManager.class), mStatusBarStateController, - mPeopleNotificationIdentifier); + mPeopleNotificationIdentifier, + mock(OnUserInteractionCallback.class)); row.setAboveShelfChangedListener(aboveShelf -> { }); mBindStage.getStageParams(entry).requireContentViews(extraInflationFlags); inflateAndWait(entry); 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 fec467706b7b..9a6674e165e4 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 @@ -74,13 +74,13 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger; import com.android.systemui.statusbar.notification.NotificationFilter; import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotifCollection; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.statusbar.notification.collection.NotificationRankingManager; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -239,7 +239,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mStackScroller.setScrimController(mock(ScrimController.class)); mStackScroller.setGroupManager(mGroupManager); mStackScroller.setEmptyShadeView(mEmptyShadeView); - mStackScroller.setIconAreaController(mNotificationIconAreaController); // Stub out functionality that isn't necessary to test. doNothing().when(mBar) @@ -437,9 +436,9 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test - public void testOnDensityOrFontScaleChanged_reInflatesFooterViews() { + public void testReInflatesFooterViews() { clearInvocations(mStackScroller); - mStackScroller.onDensityOrFontScaleChanged(); + mStackScroller.reinflateViews(); verify(mStackScroller).setFooterView(any()); verify(mStackScroller).setEmptyShadeView(any()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java new file mode 100644 index 000000000000..e3acf0213725 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java @@ -0,0 +1,115 @@ +/* + * 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.stack; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.testing.AndroidTestingRunner; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.statusbar.notification.DynamicPrivacyController; +import com.android.systemui.statusbar.notification.row.NotificationGutsManager; +import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.tuner.TunerService; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Tests for {@link NotificationStackScrollLayoutController}. + */ +@SmallTest +@RunWith(AndroidTestingRunner.class) +public class NotificationStackScrollerControllerTest extends SysuiTestCase { + + @Mock + private NotificationGutsManager mNotificationGutsManager; + @Mock + private HeadsUpManagerPhone mHeadsUpManager; + @Mock + private NotificationRoundnessManager mNotificationRoundnessManager; + @Mock + private TunerService mTunerService; + @Mock + private AmbientState mAmbientState; + @Mock + private DynamicPrivacyController mDynamicPrivacyController; + @Mock + private ConfigurationController mConfigurationController; + @Mock + private NotificationStackScrollLayout mNotificationStackScrollLayout; + + NotificationStackScrollLayoutController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mController = new NotificationStackScrollLayoutController( + true, + mNotificationGutsManager, + mHeadsUpManager, + mNotificationRoundnessManager, + mTunerService, + mDynamicPrivacyController, + mConfigurationController + ); + + when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(true); + } + + + @Test + public void testAttach_viewAlreadyAttached() { + mController.attach(mNotificationStackScrollLayout); + + verify(mConfigurationController).addCallback( + any(ConfigurationController.ConfigurationListener.class)); + } + @Test + public void testAttach_viewAttachedAfterInit() { + when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(false); + + mController.attach(mNotificationStackScrollLayout); + + verify(mConfigurationController, never()).addCallback( + any(ConfigurationController.ConfigurationListener.class)); + + mController.mOnAttachStateChangeListener.onViewAttachedToWindow( + mNotificationStackScrollLayout); + + verify(mConfigurationController).addCallback( + any(ConfigurationController.ConfigurationListener.class)); + } + + @Test + public void testOnDensityOrFontScaleChanged_reInflatesFooterViews() { + mController.attach(mNotificationStackScrollLayout); + mController.mConfigurationListener.onDensityOrFontScaleChanged(); + verify(mNotificationStackScrollLayout).reinflateViews(); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java index 64907eef2dd0..f1c8ece58fda 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java @@ -43,6 +43,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.statusbar.NotificationMediaManager; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.policy.KeyguardStateController; import org.junit.Before; @@ -76,7 +77,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { @Mock private ScrimController mScrimController; @Mock - private StatusBar mStatusBar; + private BiometricUnlockController.BiometricModeListener mBiometricModeListener; @Mock private ShadeController mShadeController; @Mock @@ -105,11 +106,12 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { mDependency.injectTestDependency(NotificationMediaManager.class, mMediaManager); res.addOverride(com.android.internal.R.integer.config_wakeUpDelayDoze, 0); mBiometricUnlockController = new BiometricUnlockController(mContext, mDozeScrimController, - mKeyguardViewMediator, mScrimController, mStatusBar, mShadeController, + mKeyguardViewMediator, mScrimController, mShadeController, mNotificationShadeWindowController, mKeyguardStateController, mHandler, mUpdateMonitor, res.getResources(), mKeyguardBypassController, mDozeParameters, mMetricsLogger, mDumpManager); mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager); + mBiometricUnlockController.setBiometricModeListener(mBiometricModeListener); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java index a6e29181e435..37ccac0b23b3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java @@ -36,15 +36,16 @@ import androidx.test.filters.SmallTest; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; import com.android.systemui.assist.AssistManager; +import com.android.systemui.biometrics.AuthController; import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.StatusBarStateControllerImpl; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; @@ -68,7 +69,6 @@ public class DozeServiceHostTest extends SysuiTestCase { @Mock private HeadsUpManagerPhone mHeadsUpManager; @Mock private ScrimController mScrimController; @Mock private DozeScrimController mDozeScrimController; - @Mock private VisualStabilityManager mVisualStabilityManager; @Mock private KeyguardViewMediator mKeyguardViewMediator; @Mock private StatusBarStateControllerImpl mStatusBarStateController; @Mock private BatteryController mBatteryController; @@ -89,6 +89,7 @@ public class DozeServiceHostTest extends SysuiTestCase { @Mock private View mAmbientIndicationContainer; @Mock private BiometricUnlockController mBiometricUnlockController; @Mock private LockscreenLockIconController mLockscreenLockIconController; + @Mock private AuthController mAuthController; @Before public void setup() { @@ -97,13 +98,16 @@ public class DozeServiceHostTest extends SysuiTestCase { mStatusBarStateController, mDeviceProvisionedController, mHeadsUpManager, mBatteryController, mScrimController, () -> mBiometricUnlockController, mKeyguardViewMediator, () -> mAssistManager, mDozeScrimController, - mKeyguardUpdateMonitor, mVisualStabilityManager, mPulseExpansionHandler, + mKeyguardUpdateMonitor, mPulseExpansionHandler, mNotificationShadeWindowController, mNotificationWakeUpCoordinator, - mLockscreenLockIconController); - - mDozeServiceHost.initialize(mStatusBar, mNotificationIconAreaController, - mStatusBarKeyguardViewManager, mNotificationShadeWindowViewController, - mNotificationPanel, mAmbientIndicationContainer); + mLockscreenLockIconController, mAuthController, mNotificationIconAreaController); + + mDozeServiceHost.initialize( + mStatusBar, + mStatusBarKeyguardViewManager, + mNotificationShadeWindowViewController, + mNotificationPanel, + mAmbientIndicationContainer); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java index 6d642ec44314..2239b1b96ac8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java @@ -33,9 +33,10 @@ import com.android.systemui.bubbles.BubbleController; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.AlertingNotificationManager; import com.android.systemui.statusbar.AlertingNotificationManagerTest; -import com.android.systemui.statusbar.notification.VisualStabilityManager; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import com.android.systemui.statusbar.policy.ConfigurationController; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java index d1a439f99702..5222ffff2637 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java @@ -17,8 +17,6 @@ package com.android.systemui.statusbar.phone; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -29,10 +27,13 @@ import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.demomode.DemoModeController; +import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; +import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import org.junit.Before; import org.junit.Test; @@ -48,8 +49,6 @@ public class NotificationIconAreaControllerTest extends SysuiTestCase { @Mock private NotificationListener mListener; @Mock - StatusBar mStatusBar; - @Mock StatusBarStateController mStatusBarStateController; @Mock NotificationWakeUpCoordinator mWakeUpCoordinator; @@ -58,26 +57,37 @@ public class NotificationIconAreaControllerTest extends SysuiTestCase { @Mock NotificationMediaManager mNotificationMediaManager; @Mock - NotificationIconContainer mNotificationIconContainer; - @Mock DozeParameters mDozeParameters; @Mock - NotificationShadeWindowView mNotificationShadeWindowView; + CommonNotifCollection mNotifCollection; + @Mock + DarkIconDispatcher mDarkIconDispatcher; + @Mock + StatusBarWindowController mStatusBarWindowController; private NotificationIconAreaController mController; @Mock private BubbleController mBubbleController; + @Mock private DemoModeController mDemoModeController; + @Mock + private NotificationIconContainer mAodIcons; @Before public void setup() { MockitoAnnotations.initMocks(this); - when(mStatusBar.getNotificationShadeWindowView()).thenReturn(mNotificationShadeWindowView); - when(mNotificationShadeWindowView.findViewById(anyInt())).thenReturn( - mNotificationIconContainer); - - mController = new NotificationIconAreaController(mContext, mStatusBar, - mStatusBarStateController, mWakeUpCoordinator, mKeyguardBypassController, - mNotificationMediaManager, mListener, mDozeParameters, mBubbleController); + mController = new NotificationIconAreaController( + mContext, + mStatusBarStateController, + mWakeUpCoordinator, + mKeyguardBypassController, + mNotificationMediaManager, + mListener, + mDozeParameters, + mBubbleController, + mDemoModeController, + mDarkIconDispatcher, + mStatusBarWindowController); + mController.setupAodIcons(mAodIcons); } @Test @@ -98,7 +108,7 @@ public class NotificationIconAreaControllerTest extends SysuiTestCase { public void testAppearResetsTranslation() { when(mDozeParameters.shouldControlScreenOff()).thenReturn(false); mController.appearAodIcons(); - verify(mNotificationIconContainer).setTranslationY(0); - verify(mNotificationIconContainer).setAlpha(1.0f); + verify(mAodIcons).setTranslationY(0); + verify(mAodIcons).setAlpha(1.0f); } } 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 a0c0e7979084..c9e9d94d8a79 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 @@ -251,9 +251,13 @@ public class NotificationPanelViewTest extends SysuiTestCase { mConversationNotificationManager, mMediaHiearchyManager, mBiometricUnlockController, mStatusBarKeyguardViewManager, () -> mKeyguardClockSwitchController, - mNotificationStackScrollLayoutController); - mNotificationPanelViewController.initDependencies(mStatusBar, mGroupManager, - mNotificationShelfController, mNotificationAreaController, mScrimController); + mNotificationStackScrollLayoutController, + mNotificationAreaController); + mNotificationPanelViewController.initDependencies( + mStatusBar, + mGroupManager, + mNotificationShelfController, + mScrimController); mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager); mNotificationPanelViewController.setBar(mPanelBar); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java index 8c37cf1514fd..fcea17c5a6b5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java @@ -57,7 +57,7 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidTestingRunner.class) @RunWithLooper @SmallTest -public class NotificationShadeWindowControllerTest extends SysuiTestCase { +public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { @Mock private WindowManager mWindowManager; @Mock private DozeParameters mDozeParameters; @@ -72,7 +72,7 @@ public class NotificationShadeWindowControllerTest extends SysuiTestCase { @Mock private DumpManager mDumpManager; @Captor private ArgumentCaptor<WindowManager.LayoutParams> mLayoutParameters; - private NotificationShadeWindowController mNotificationShadeWindowController; + private NotificationShadeWindowControllerImpl mNotificationShadeWindowController; @Before public void setUp() { @@ -80,7 +80,7 @@ public class NotificationShadeWindowControllerTest extends SysuiTestCase { when(mDozeParameters.getAlwaysOn()).thenReturn(true); when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors); - mNotificationShadeWindowController = new NotificationShadeWindowController(mContext, + mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(mContext, mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController, mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController, mColorExtractor, mDumpManager); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java index 51900cb7dda1..c1d51f3beb7d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java @@ -38,6 +38,7 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.DragDownHelper; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.SuperStatusBarViewFactory; import com.android.systemui.statusbar.SysuiStatusBarStateController; @@ -101,7 +102,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { mController = new NotificationShadeWindowViewController( new InjectionInflationController( SystemUIFactory.getInstance() - .getRootComponent() + .getSysUIComponent() .createViewInstanceCreatorFactory()), mCoordinator, mPulseExpansionHandler, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java index 50d891efc62c..ccc307841491 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java @@ -47,6 +47,7 @@ import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.plugins.ActivityStarter.OnDismissAction; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.statusbar.NotificationMediaManager; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java index a71b10cf9264..3f631b1f6282 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java @@ -73,7 +73,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationTestHelper; -import com.android.systemui.statusbar.notification.row.OnDismissCallback; +import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.time.FakeSystemClock; @@ -132,7 +132,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { @Mock private Intent mContentIntentInner; @Mock - private OnDismissCallback mOnDismissCallback; + private OnUserInteractionCallback mOnUserInteractionCallback; @Mock private NotificationActivityStarter mNotificationActivityStarter; private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock()); @@ -210,7 +210,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { mFeatureFlags, mock(MetricsLogger.class), mock(StatusBarNotificationActivityStarterLogger.class), - mOnDismissCallback) + mOnUserInteractionCallback) .setStatusBar(mStatusBar) .setNotificationPresenter(mock(NotificationPresenter.class)) .setNotificationPanelViewController(mock(NotificationPanelViewController.class)) @@ -267,7 +267,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { eq(sbn.getKey()), any(NotificationVisibility.class)); // Notification calls dismiss callback to remove notification due to FLAG_AUTO_CANCEL - verify(mOnDismissCallback).onDismiss(mNotificationRow.getEntry(), REASON_CLICK); + verify(mOnUserInteractionCallback).onDismiss(mNotificationRow.getEntry(), REASON_CLICK); } @Test @@ -296,7 +296,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { verifyZeroInteractions(mContentIntent); // Notification should not be cancelled. - verify(mOnDismissCallback, never()).onDismiss(eq(mNotificationRow.getEntry()), anyInt()); + verify(mOnUserInteractionCallback, never()).onDismiss(eq(mNotificationRow.getEntry()), + anyInt()); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java index e4f481241257..c0ebfadf6b57 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java @@ -43,15 +43,16 @@ import com.android.systemui.statusbar.KeyguardIndicationController; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationRemoteInputManager; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationViewHierarchyManager; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 03f1c68df84b..8462386aaf2d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -83,10 +83,12 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.demomode.DemoModeController; import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.plugins.ActivityStarter.OnDismissAction; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.PluginDependencyProvider; @@ -97,12 +99,12 @@ import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.stackdivider.Divider; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.KeyguardIndicationController; -import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationViewHierarchyManager; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.RemoteInputController; @@ -115,9 +117,9 @@ import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationFilter; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; -import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.init.NotificationsController; import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl; @@ -252,6 +254,7 @@ public class StatusBarTest extends SysuiTestCase { @Mock private ExtensionController mExtensionController; @Mock private UserInfoControllerImpl mUserInfoControllerImpl; @Mock private PhoneStatusBarPolicy mPhoneStatusBarPolicy; + @Mock private DemoModeController mDemoModeController; @Mock private Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy; private ShadeController mShadeController; private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock()); @@ -402,7 +405,6 @@ public class StatusBarTest extends SysuiTestCase { mStatusBarKeyguardViewManager, mViewMediatorCallback, mInitController, - mDarkIconDispatcher, new Handler(TestableLooper.get(this).getLooper()), mPluginDependencyProvider, mKeyguardDismissUtil, @@ -411,8 +413,10 @@ public class StatusBarTest extends SysuiTestCase { mPhoneStatusBarPolicy, mKeyguardIndicationController, mDismissCallbackRegistry, + mDemoModeController, mNotificationShadeDepthControllerLazy, - mStatusBarTouchableRegionManager); + mStatusBarTouchableRegionManager, + mNotificationIconAreaController); when(mNotificationShadeWindowView.findViewById(R.id.lock_icon_container)).thenReturn( mLockIconContainer); @@ -430,7 +434,6 @@ public class StatusBarTest extends SysuiTestCase { mStatusBar.mNotificationShadeWindowView = mNotificationShadeWindowView; mStatusBar.mNotificationPanelViewController = mNotificationPanelViewController; mStatusBar.mDozeScrimController = mDozeScrimController; - mStatusBar.mNotificationIconAreaController = mNotificationIconAreaController; mStatusBar.mPresenter = mNotificationPresenter; mStatusBar.mKeyguardIndicationController = mKeyguardIndicationController; mStatusBar.mBarService = mBarService; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java index eca48c8c2ee1..23fa6fd5e4ca 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java @@ -29,6 +29,7 @@ import android.testing.TestableLooper; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.demomode.DemoModeController; import com.android.systemui.power.EnhancedEstimates; import org.junit.Assert; @@ -44,17 +45,21 @@ import org.mockito.MockitoAnnotations; @TestableLooper.RunWithLooper public class BatteryControllerTest extends SysuiTestCase { - @Mock - private PowerManager mPowerManager; - @Mock - private BroadcastDispatcher mBroadcastDispatcher; + @Mock private PowerManager mPowerManager; + @Mock private BroadcastDispatcher mBroadcastDispatcher; + @Mock private DemoModeController mDemoModeController; private BatteryControllerImpl mBatteryController; @Before public void setUp() { MockitoAnnotations.initMocks(this); - mBatteryController = new BatteryControllerImpl(getContext(), mock(EnhancedEstimates.class), - mPowerManager, mBroadcastDispatcher, new Handler(), new Handler()); + mBatteryController = new BatteryControllerImpl(getContext(), + mock(EnhancedEstimates.class), + mPowerManager, + mBroadcastDispatcher, + mDemoModeController, + new Handler(), + new Handler()); mBatteryController.init(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index aef454fc1374..7db1b836f428 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -66,6 +66,7 @@ import com.android.settingslib.net.DataUsageController; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.demomode.DemoModeController; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; @@ -113,6 +114,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected DeviceProvisionedController mMockProvisionController; protected DeviceProvisionedListener mUserCallback; protected Instrumentation mInstrumentation; + protected DemoModeController mDemoModeController; protected int mSubId; @@ -146,6 +148,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { res.addOverride(R.string.cell_data_off_content_description, NO_DATA_STRING); res.addOverride(R.string.not_default_data_content_description, NOT_DEFAULT_DATA_STRING); + mDemoModeController = mock(DemoModeController.class); mMockWm = mock(WifiManager.class); mMockTm = mock(TelephonyManager.class); mMockSm = mock(SubscriptionManager.class); @@ -200,10 +203,21 @@ public class NetworkControllerBaseTest extends SysuiTestCase { return null; }).when(mMockProvisionController).addCallback(any()); - mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, - mMockNsm, mMockSm, mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler, - mock(AccessPointControllerImpl.class), mock(DataUsageController.class), - mMockSubDefaults, mMockProvisionController, mMockBd); + mNetworkController = new NetworkControllerImpl(mContext, + mMockCm, + mMockTm, + mMockWm, + mMockNsm, + mMockSm, + mConfig, + TestableLooper.get(this).getLooper(), + mCallbackHandler, + mock(AccessPointControllerImpl.class), + mock(DataUsageController.class), + mMockSubDefaults, + mMockProvisionController, + mMockBd, + mDemoModeController); setupNetworkController(); // Trigger blank callbacks to always get the current state (some tests don't trigger @@ -254,7 +268,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler, mock(AccessPointControllerImpl.class), mock(DataUsageController.class), mMockSubDefaults, - mock(DeviceProvisionedController.class), mMockBd); + mock(DeviceProvisionedController.class), mMockBd, mDemoModeController); setupNetworkController(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java index 6fffcff41a4f..d8aa29e9f766 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java @@ -106,7 +106,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler, mock(AccessPointControllerImpl.class), mock(DataUsageController.class), mMockSubDefaults, - mock(DeviceProvisionedController.class), mMockBd); + mock(DeviceProvisionedController.class), mMockBd, mDemoModeController); setupNetworkController(); setupDefaultSignal(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java index 3b2743775721..61f71b758d80 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java @@ -63,7 +63,8 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler, mock(AccessPointControllerImpl.class), mock(DataUsageController.class), - mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd); + mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd, + mDemoModeController); setupNetworkController(); verifyLastMobileDataIndicators(false, -1, 0); @@ -81,7 +82,8 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler, mock(AccessPointControllerImpl.class), mock(DataUsageController.class), - mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd); + mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd, + mDemoModeController); mNetworkController.registerListeners(); // Wait for the main looper to execute the previous command @@ -147,7 +149,8 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler, mock(AccessPointControllerImpl.class), mock(DataUsageController.class), - mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd); + mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd, + mDemoModeController); setupNetworkController(); // No Subscriptions. diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 833aeecc4c47..c41f4007aa59 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -1530,12 +1530,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub int serviceCount = userState.mBoundServices.size(); for (int i = 0; i < serviceCount; i++) { AccessibilityServiceConnection service = userState.mBoundServices.get(i); - relevantEventTypes |= isClientInPackageWhitelist(service.getServiceInfo(), client) + relevantEventTypes |= isClientInPackageAllowlist(service.getServiceInfo(), client) ? service.getRelevantEventTypes() : 0; } - relevantEventTypes |= isClientInPackageWhitelist( + relevantEventTypes |= isClientInPackageAllowlist( mUiAutomationManager.getServiceInfo(), client) ? mUiAutomationManager.getRelevantEventTypes() : 0; @@ -1571,7 +1571,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } - private static boolean isClientInPackageWhitelist( + private static boolean isClientInPackageAllowlist( @Nullable AccessibilityServiceInfo serviceInfo, Client client) { if (serviceInfo == null) return false; @@ -1590,7 +1590,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub Slog.d(LOG_TAG, "Dropping events: " + Arrays.toString(clientPackages) + " -> " + serviceInfo.getComponentName().flattenToShortString() - + " due to not being in package whitelist " + + " due to not being in package allowlist " + Arrays.toString(serviceInfo.packageNames)); } } @@ -1991,9 +1991,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } private void updateLegacyCapabilitiesLocked(AccessibilityUserState userState) { - // Up to JB-MR1 we had a white list with services that can enable touch + // Up to JB-MR1 we had a allowlist with services that can enable touch // exploration. When a service is first started we show a dialog to the - // use to get a permission to white list the service. + // use to get a permission to allowlist the service. final int installedServiceCount = userState.mInstalledServices.size(); for (int i = 0; i < installedServiceCount; i++) { AccessibilityServiceInfo serviceInfo = userState.mInstalledServices.get(i); @@ -2261,9 +2261,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } if (service.getServiceInfo().getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1) { - // Up to JB-MR1 we had a white list with services that can enable touch + // Up to JB-MR1 we had a allowlist with services that can enable touch // exploration. When a service is first started we show a dialog to the - // use to get a permission to white list the service. + // use to get a permission to allowlist the service. if (userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) { return true; } else if (mEnableTouchExplorationDialog == null diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index 663fd6259fd4..ad85784ca066 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -360,7 +360,7 @@ public final class AutofillManagerService @Override // from SystemService public boolean isUserSupported(TargetUser user) { - return user.getUserInfo().isFull() || user.getUserInfo().isManagedProfile(); + return user.isFull() || user.isManagedProfile(); } @Override // from SystemService diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java index ea94ad0b3c20..e742015916e7 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java @@ -219,7 +219,7 @@ public final class ContentCaptureManagerService extends @Override // from SystemService public boolean isUserSupported(TargetUser user) { - return user.getUserInfo().isFull() || user.getUserInfo().isManagedProfile(); + return user.isFull() || user.isManagedProfile(); } @Override // from SystemService diff --git a/services/core/java/android/os/UserManagerInternal.java b/services/core/java/android/os/UserManagerInternal.java index fbe8c04bd59c..61e8128bd510 100644 --- a/services/core/java/android/os/UserManagerInternal.java +++ b/services/core/java/android/os/UserManagerInternal.java @@ -262,8 +262,7 @@ public abstract class UserManagerInternal { public abstract boolean hasUserRestriction(String restriction, int userId); /** - * Gets an {@link UserInfo} for the given {@code userId}, or {@code null} if not - * found. + * Gets a {@link UserInfo} for the given {@code userId}, or {@code null} if not found. */ public abstract @Nullable UserInfo getUserInfo(@UserIdInt int userId); diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 97f3b373f63e..ee794badad88 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -20,14 +20,14 @@ import static android.Manifest.permission.CONNECTIVITY_INTERNAL; import static android.Manifest.permission.NETWORK_SETTINGS; import static android.Manifest.permission.OBSERVE_NETWORK_POLICY; import static android.Manifest.permission.SHUTDOWN; -import static android.net.INetd.FIREWALL_BLACKLIST; +import static android.net.INetd.FIREWALL_ALLOWLIST; import static android.net.INetd.FIREWALL_CHAIN_DOZABLE; import static android.net.INetd.FIREWALL_CHAIN_NONE; import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE; import static android.net.INetd.FIREWALL_CHAIN_STANDBY; +import static android.net.INetd.FIREWALL_DENYLIST; import static android.net.INetd.FIREWALL_RULE_ALLOW; import static android.net.INetd.FIREWALL_RULE_DENY; -import static android.net.INetd.FIREWALL_WHITELIST; import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE; import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE; import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY; @@ -1575,7 +1575,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub { enforceSystemUid(); try { mNetdService.firewallSetFirewallType( - enabled ? INetd.FIREWALL_WHITELIST : INetd.FIREWALL_BLACKLIST); + enabled ? INetd.FIREWALL_ALLOWLIST : INetd.FIREWALL_DENYLIST); mFirewallEnabled = enabled; } catch (RemoteException | ServiceSpecificException e) { throw new IllegalStateException(e); @@ -1608,7 +1608,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub { int numUids = 0; if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName); - if (getFirewallType(chain) == FIREWALL_WHITELIST) { + if (getFirewallType(chain) == FIREWALL_ALLOWLIST) { // Close all sockets on all non-system UIDs... ranges = new UidRangeParcel[] { // TODO: is there a better way of finding all existing users? If so, we could @@ -1714,13 +1714,13 @@ public class NetworkManagementService extends INetworkManagementService.Stub { private int getFirewallType(int chain) { switch (chain) { case FIREWALL_CHAIN_STANDBY: - return FIREWALL_BLACKLIST; + return FIREWALL_DENYLIST; case FIREWALL_CHAIN_DOZABLE: - return FIREWALL_WHITELIST; + return FIREWALL_ALLOWLIST; case FIREWALL_CHAIN_POWERSAVE: - return FIREWALL_WHITELIST; + return FIREWALL_ALLOWLIST; default: - return isFirewallEnabled() ? FIREWALL_WHITELIST : FIREWALL_BLACKLIST; + return isFirewallEnabled() ? FIREWALL_ALLOWLIST : FIREWALL_DENYLIST; } } @@ -1822,7 +1822,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub { private @NonNull String getFirewallRuleName(int chain, int rule) { String ruleName; - if (getFirewallType(chain) == FIREWALL_WHITELIST) { + if (getFirewallType(chain) == FIREWALL_ALLOWLIST) { if (rule == FIREWALL_RULE_ALLOW) { ruleName = "allow"; } else { @@ -1856,7 +1856,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub { private int getFirewallRuleType(int chain, int rule) { if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) { - return getFirewallType(chain) == FIREWALL_WHITELIST + return getFirewallType(chain) == FIREWALL_ALLOWLIST ? INetd.FIREWALL_RULE_DENY : INetd.FIREWALL_RULE_ALLOW; } return rule; diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index d1d9c0e3a285..b72985cc8f2c 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -1141,13 +1141,6 @@ class StorageManagerService extends IStorageManager.Stub } private void completeUnlockUser(int userId) { - // If user 0 has completed unlock, perform a one-time migration of legacy obb data - // to its new location. This may take time depending on the size of the data to be copied - // so it's done on the StorageManager handler thread. - if (userId == 0) { - mPmInternal.migrateLegacyObbData(); - } - onKeyguardStateChanged(false); // Record user as started so newly mounted volumes kick off events @@ -1540,9 +1533,21 @@ class StorageManagerService extends IStorageManager.Stub mFuseMountedUser.remove(vol.getMountUserId()); } else if (mVoldAppDataIsolationEnabled){ final int userId = vol.getMountUserId(); - mFuseMountedUser.add(userId); // Async remount app storage so it won't block the main thread. new Thread(() -> { + + // If user 0 has completed unlock, perform a one-time migration of legacy + // obb data to its new location. This may take time depending on the size of + // the data to be copied so it's done on the StorageManager worker thread. + // This needs to be finished before start mounting obb directories. + if (userId == 0) { + mPmInternal.migrateLegacyObbData(); + } + + // Add fuse mounted user after migration to prevent ProcessList tries to + // create obb directory before migration is done. + mFuseMountedUser.add(userId); + Map<Integer, String> pidPkgMap = null; // getProcessesWithPendingBindMounts() could fail when a new app process is // starting and it's not planning to mount storage dirs in zygote, but it's diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java index 1496e926b95b..84d01ec3598d 100644 --- a/services/core/java/com/android/server/SystemService.java +++ b/services/core/java/com/android/server/SystemService.java @@ -23,6 +23,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.SystemApi.Client; +import android.annotation.UserIdInt; import android.app.ActivityThread; import android.content.Context; import android.content.pm.UserInfo; @@ -131,45 +132,89 @@ public abstract class SystemService { */ @SystemApi(client = Client.SYSTEM_SERVER) public static final class TargetUser { - @NonNull - private final UserInfo mUserInfo; + + // NOTE: attributes below must be immutable while ther user is running (i.e., from the + // moment it's started until after it's shutdown). + private final @UserIdInt int mUserId; + private final boolean mFull; + private final boolean mManagedProfile; + private final boolean mPreCreated; /** @hide */ public TargetUser(@NonNull UserInfo userInfo) { - mUserInfo = userInfo; + mUserId = userInfo.id; + mFull = userInfo.isFull(); + mManagedProfile = userInfo.isManagedProfile(); + mPreCreated = userInfo.preCreated; } /** - * @return The information about the user. <b>NOTE: </b> this is a "live" object - * referenced by {@link UserManagerService} and hence should not be modified. + * Checks if the target user is {@link UserInfo#isFull() full}. * * @hide */ - @NonNull - public UserInfo getUserInfo() { - return mUserInfo; + public boolean isFull() { + return mFull; + } + + /** + * Checks if the target user is a managed profile. + * + * @hide + */ + public boolean isManagedProfile() { + return mManagedProfile; + } + + /** + * Checks if the target user is a pre-created user. + * + * @hide + */ + public boolean isPreCreated() { + return mPreCreated; } /** - * @return the target {@link UserHandle}. + * Gets the target user's {@link UserHandle}. */ @NonNull public UserHandle getUserHandle() { - return mUserInfo.getUserHandle(); + return UserHandle.of(mUserId); } /** - * @return the integer user id + * Gets the target user's id. * * @hide */ - public int getUserIdentifier() { - return mUserInfo.id; + public @UserIdInt int getUserIdentifier() { + return mUserId; } @Override public String toString() { - return Integer.toString(getUserIdentifier()); + return Integer.toString(mUserId); + } + + /** + * @hide + */ + public void dump(@NonNull StringBuilder builder) { + builder.append(getUserIdentifier()); + + if (!isFull() && !isManagedProfile()) return; + + builder.append('('); + boolean addComma = false; + if (isFull()) { + builder.append("full"); + } + if (isManagedProfile()) { + if (addComma) builder.append(','); + builder.append("mp"); + } + builder.append(')'); } } diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java index 74bb7d7e90f1..df966c1ea6ac 100644 --- a/services/core/java/com/android/server/SystemServiceManager.java +++ b/services/core/java/com/android/server/SystemServiceManager.java @@ -27,7 +27,10 @@ import android.os.UserHandle; import android.os.UserManagerInternal; import android.util.ArrayMap; import android.util.Slog; +import android.util.SparseArray; +import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.Preconditions; import com.android.server.SystemService.TargetUser; import com.android.server.utils.TimingsTraceAndSlog; @@ -74,6 +77,13 @@ public class SystemServiceManager { private UserManagerInternal mUserManagerInternal; + /** + * Map of started {@link TargetUser TargetUsers} by user id; users are added on start and + * removed after they're completely shut down. + */ + @GuardedBy("mTargetUsers") + private final SparseArray<TargetUser> mTargetUsers = new SparseArray<>(); + SystemServiceManager(Context context) { mContext = context; } @@ -240,21 +250,26 @@ public class SystemServiceManager { mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); } - private @NonNull UserInfo getUserInfo(@UserIdInt int userHandle) { - if (mUserManagerInternal == null) { - throw new IllegalStateException("mUserManagerInternal not set yet"); + private @NonNull TargetUser getTargetUser(@UserIdInt int userHandle) { + final TargetUser targetUser; + synchronized (mTargetUsers) { + targetUser = mTargetUsers.get(userHandle); } - final UserInfo userInfo = mUserManagerInternal.getUserInfo(userHandle); - if (userInfo == null) { - throw new IllegalStateException("No UserInfo for " + userHandle); - } - return userInfo; + Preconditions.checkState(targetUser != null, "No TargetUser for " + userHandle); + return targetUser; } /** * Starts the given user. */ public void startUser(final @NonNull TimingsTraceAndSlog t, final @UserIdInt int userHandle) { + // Create cached TargetUser + final UserInfo userInfo = mUserManagerInternal.getUserInfo(userHandle); + Preconditions.checkState(userInfo != null, "No UserInfo for " + userHandle); + synchronized (mTargetUsers) { + mTargetUsers.put(userHandle, new TargetUser(userInfo)); + } + onUser(t, START, userHandle); } @@ -291,6 +306,11 @@ public class SystemServiceManager { */ public void cleanupUser(final @UserIdInt int userHandle) { onUser(CLEANUP, userHandle); + + // Remove cached TargetUser + synchronized (mTargetUsers) { + mTargetUsers.remove(userHandle); + } } private void onUser(@NonNull String onWhat, @UserIdInt int userHandle) { @@ -306,9 +326,9 @@ public class SystemServiceManager { @UserIdInt int curUserId, @UserIdInt int prevUserId) { t.traceBegin("ssm." + onWhat + "User-" + curUserId); Slog.i(TAG, "Calling on" + onWhat + "User " + curUserId); - final TargetUser curUser = new TargetUser(getUserInfo(curUserId)); + final TargetUser curUser = getTargetUser(curUserId); final TargetUser prevUser = prevUserId == UserHandle.USER_NULL ? null - : new TargetUser(getUserInfo(prevUserId)); + : getTargetUser(prevUserId); final int serviceLen = mServices.size(); for (int i = 0; i < serviceLen; i++) { final SystemService service = mServices.get(i); @@ -437,7 +457,7 @@ public class SystemServiceManager { */ public void dump() { StringBuilder builder = new StringBuilder(); - builder.append("Current phase: ").append(mCurrentPhase).append("\n"); + builder.append("Current phase: ").append(mCurrentPhase).append('\n'); builder.append("Services:\n"); final int startedLen = mServices.size(); for (int i = 0; i < startedLen; i++) { @@ -447,6 +467,14 @@ public class SystemServiceManager { .append("\n"); } + builder.append("Target users: "); + final int targetUsersSize = mTargetUsers.size(); + for (int i = 0; i < targetUsersSize; i++) { + mTargetUsers.valueAt(i).dump(builder); + if (i != targetUsersSize - 1) builder.append(','); + } + builder.append('\n'); + Slog.e(TAG, builder.toString()); } } diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index 32d02fb17983..96d973ec5272 100644 --- a/services/core/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java @@ -127,6 +127,7 @@ public class VibratorService extends IVibratorService.Stub private final int mPreviousVibrationsLimit; private final boolean mAllowPriorityVibrationsInLowPowerMode; private final List<Integer> mSupportedEffects; + private final List<Integer> mSupportedPrimitives; private final long mCapabilities; private final int mDefaultVibrationAmplitude; private final SparseArray<VibrationEffect> mFallbackEffects; @@ -184,6 +185,8 @@ public class VibratorService extends IVibratorService.Stub static native int[] vibratorGetSupportedEffects(long controllerPtr); + static native int[] vibratorGetSupportedPrimitives(long controllerPtr); + static native long vibratorPerformEffect( long controllerPtr, long effect, long strength, Vibration vibration); @@ -397,6 +400,7 @@ public class VibratorService extends IVibratorService.Stub mNativeWrapper.vibratorOff(); mSupportedEffects = asList(mNativeWrapper.vibratorGetSupportedEffects()); + mSupportedPrimitives = asList(mNativeWrapper.vibratorGetSupportedPrimitives()); mCapabilities = mNativeWrapper.vibratorGetCapabilities(); mContext = context; @@ -647,8 +651,11 @@ public class VibratorService extends IVibratorService.Stub @Override // Binder call public boolean[] arePrimitivesSupported(int[] primitiveIds) { boolean[] supported = new boolean[primitiveIds.length]; - if (hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { - Arrays.fill(supported, true); + if (!hasCapability(IVibrator.CAP_COMPOSE_EFFECTS) || mSupportedPrimitives == null) { + return supported; + } + for (int i = 0; i < primitiveIds.length; i++) { + supported[i] = mSupportedPrimitives.contains(primitiveIds[i]); } return supported; } @@ -1501,6 +1508,7 @@ public class VibratorService extends IVibratorService.Stub pw.println(" mNotificationIntensity=" + mNotificationIntensity); pw.println(" mRingIntensity=" + mRingIntensity); pw.println(" mSupportedEffects=" + mSupportedEffects); + pw.println(" mSupportedPrimitives=" + mSupportedPrimitives); pw.println(); pw.println(" Previous ring vibrations:"); for (VibrationInfo info : mPreviousRingVibrations) { @@ -1759,6 +1767,11 @@ public class VibratorService extends IVibratorService.Stub return VibratorService.vibratorGetSupportedEffects(mNativeControllerPtr); } + /** Returns all compose primitives supported by the device vibrator. */ + public int[] vibratorGetSupportedPrimitives() { + return VibratorService.vibratorGetSupportedPrimitives(mNativeControllerPtr); + } + /** Turns vibrator on to perform one of the supported effects. */ public long vibratorPerformEffect(long effect, long strength, Vibration vibration) { return VibratorService.vibratorPerformEffect( diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 23e9d1b552d5..6328cb60cf73 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -493,11 +493,6 @@ public final class ActiveServices { } ServiceRecord r = res.record; - - if (allowBackgroundActivityStarts) { - r.allowBgActivityStartsOnServiceStart(); - } - setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, r, allowBackgroundActivityStarts); @@ -710,6 +705,9 @@ public final class ActiveServices { "Not potential delay (user " + r.userId + " not started): " + r); } } + if (allowBackgroundActivityStarts) { + r.allowBgActivityStartsOnServiceStart(); + } ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); return cmp; } diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java index 0f2dfcc699e2..757b4e83e120 100644 --- a/services/core/java/com/android/server/am/CoreSettingsObserver.java +++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java @@ -100,15 +100,20 @@ final class CoreSettingsObserver extends ContentObserver { sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS, String.class); sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS_GLES, String.class); sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYER_APP, String.class); - sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_ALL_APPS, int.class); - sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_OPT_IN_APPS, String.class); + sGlobalSettingToTypeMap.put(Settings.Global.UPDATABLE_DRIVER_ALL_APPS, int.class); sGlobalSettingToTypeMap.put( - Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS, String.class); - sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_OPT_OUT_APPS, String.class); - sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_DENYLIST, String.class); - sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_ALLOWLIST, String.class); - sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_DENYLISTS, String.class); - sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, String.class); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS, String.class); + sGlobalSettingToTypeMap.put( + Settings.Global.UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS, String.class); + sGlobalSettingToTypeMap.put( + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_OUT_APPS, String.class); + sGlobalSettingToTypeMap.put( + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLIST, String.class); + sGlobalSettingToTypeMap.put( + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST, String.class); + sGlobalSettingToTypeMap.put( + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS, String.class); + sGlobalSettingToTypeMap.put(Settings.Global.UPDATABLE_DRIVER_SPHAL_LIBRARIES, String.class); // add other global settings here... sDeviceConfigEntries.add(new DeviceConfigEntry<Boolean>( diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 2e8660e1317a..4673ecde7a68 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -2222,7 +2222,8 @@ public final class ProcessList { // access /mnt/user anyway. && app.mountMode != Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE && app.mountMode != Zygote.MOUNT_EXTERNAL_PASS_THROUGH - && app.mountMode != Zygote.MOUNT_EXTERNAL_INSTALLER; + && app.mountMode != Zygote.MOUNT_EXTERNAL_INSTALLER + && app.mountMode != Zygote.MOUNT_EXTERNAL_NONE; } private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint, diff --git a/services/core/java/com/android/server/am/UidObserverController.java b/services/core/java/com/android/server/am/UidObserverController.java index 4c4dd8b8defa..4d9260aec62e 100644 --- a/services/core/java/com/android/server/am/UidObserverController.java +++ b/services/core/java/com/android/server/am/UidObserverController.java @@ -86,15 +86,17 @@ public class UidObserverController { } mService.mUiHandler.post(this::dispatchUidsChanged); } - final int NA = mAvailUidChanges.size(); - if (NA > 0) { - pendingChange = mAvailUidChanges.remove(NA-1); - if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, - "Retrieving available item: " + pendingChange); + final int size = mAvailUidChanges.size(); + if (size > 0) { + pendingChange = mAvailUidChanges.remove(size - 1); + if (DEBUG_UID_OBSERVERS) { + Slog.i(TAG_UID_OBSERVERS, "Retrieving available item: " + pendingChange); + } } else { pendingChange = new UidRecord.ChangeItem(); - if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, - "Allocating new item: " + pendingChange); + if (DEBUG_UID_OBSERVERS) { + Slog.i(TAG_UID_OBSERVERS, "Allocating new item: " + pendingChange); + } } if (uidRec != null) { uidRec.pendingChange = pendingChange; @@ -134,7 +136,8 @@ public class UidObserverController { } } pendingChange.change = change; - pendingChange.processState = uidRec != null ? uidRec.setProcState : PROCESS_STATE_NONEXISTENT; + pendingChange.processState = uidRec != null + ? uidRec.setProcState : PROCESS_STATE_NONEXISTENT; pendingChange.capability = uidRec != null ? uidRec.setCapability : 0; pendingChange.ephemeral = uidRec != null ? uidRec.ephemeral : isEphemeralLocked(uid); pendingChange.procStateSeq = uidRec != null ? uidRec.curProcStateSeq : 0; @@ -165,13 +168,13 @@ public class UidObserverController { @VisibleForTesting void dispatchUidsChanged() { - int N; + int numUidChanges; synchronized (mService) { - N = mPendingUidChanges.size(); - if (mActiveUidChanges.length < N) { - mActiveUidChanges = new UidRecord.ChangeItem[N]; + numUidChanges = mPendingUidChanges.size(); + if (mActiveUidChanges.length < numUidChanges) { + mActiveUidChanges = new UidRecord.ChangeItem[numUidChanges]; } - for (int i=0; i<N; i++) { + for (int i = 0; i < numUidChanges; i++) { final UidRecord.ChangeItem change = mPendingUidChanges.get(i); mActiveUidChanges[i] = change; if (change.uidRecord != null) { @@ -180,21 +183,22 @@ public class UidObserverController { } } mPendingUidChanges.clear(); - if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, - "*** Delivering " + N + " uid changes"); + if (DEBUG_UID_OBSERVERS) { + Slog.i(TAG_UID_OBSERVERS, "*** Delivering " + numUidChanges + " uid changes"); + } } - mUidChangeDispatchCount += N; + mUidChangeDispatchCount += numUidChanges; int i = mUidObservers.beginBroadcast(); while (i > 0) { i--; dispatchUidsChangedForObserver(mUidObservers.getBroadcastItem(i), - (UidObserverRegistration) mUidObservers.getBroadcastCookie(i), N); + (UidObserverRegistration) mUidObservers.getBroadcastCookie(i), numUidChanges); } mUidObservers.finishBroadcast(); if (VALIDATE_UID_STATES && mUidObservers.getRegisteredCallbackCount() > 0) { - for (int j = 0; j < N; ++j) { + for (int j = 0; j < numUidChanges; ++j) { final UidRecord.ChangeItem item = mActiveUidChanges[j]; if ((item.change & UidRecord.CHANGE_GONE) != 0) { mValidateUids.remove(item.uid); @@ -217,7 +221,7 @@ public class UidObserverController { } synchronized (mService) { - for (int j = 0; j < N; j++) { + for (int j = 0; j < numUidChanges; j++) { mAvailUidChanges.add(mActiveUidChanges[j]); } } @@ -232,66 +236,72 @@ public class UidObserverController { for (int j = 0; j < changesSize; j++) { UidRecord.ChangeItem item = mActiveUidChanges[j]; final int change = item.change; - if (change == UidRecord.CHANGE_PROCSTATE && - (reg.which & ActivityManager.UID_OBSERVER_PROCSTATE) == 0) { + if (change == UidRecord.CHANGE_PROCSTATE + && (reg.mWhich & ActivityManager.UID_OBSERVER_PROCSTATE) == 0) { // No-op common case: no significant change, the observer is not // interested in all proc state changes. continue; } final long start = SystemClock.uptimeMillis(); if ((change & UidRecord.CHANGE_IDLE) != 0) { - if ((reg.which & ActivityManager.UID_OBSERVER_IDLE) != 0) { - if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, - "UID idle uid=" + item.uid); + if ((reg.mWhich & ActivityManager.UID_OBSERVER_IDLE) != 0) { + if (DEBUG_UID_OBSERVERS) { + Slog.i(TAG_UID_OBSERVERS, "UID idle uid=" + item.uid); + } observer.onUidIdle(item.uid, item.ephemeral); } } else if ((change & UidRecord.CHANGE_ACTIVE) != 0) { - if ((reg.which & ActivityManager.UID_OBSERVER_ACTIVE) != 0) { - if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, - "UID active uid=" + item.uid); + if ((reg.mWhich & ActivityManager.UID_OBSERVER_ACTIVE) != 0) { + if (DEBUG_UID_OBSERVERS) { + Slog.i(TAG_UID_OBSERVERS, "UID active uid=" + item.uid); + } observer.onUidActive(item.uid); } } - if ((reg.which & ActivityManager.UID_OBSERVER_CACHED) != 0) { + if ((reg.mWhich & ActivityManager.UID_OBSERVER_CACHED) != 0) { if ((change & UidRecord.CHANGE_CACHED) != 0) { - if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, - "UID cached uid=" + item.uid); + if (DEBUG_UID_OBSERVERS) { + Slog.i(TAG_UID_OBSERVERS, "UID cached uid=" + item.uid); + } observer.onUidCachedChanged(item.uid, true); } else if ((change & UidRecord.CHANGE_UNCACHED) != 0) { - if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, - "UID active uid=" + item.uid); + if (DEBUG_UID_OBSERVERS) { + Slog.i(TAG_UID_OBSERVERS, "UID active uid=" + item.uid); + } observer.onUidCachedChanged(item.uid, false); } } if ((change & UidRecord.CHANGE_GONE) != 0) { - if ((reg.which & ActivityManager.UID_OBSERVER_GONE) != 0) { - if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, - "UID gone uid=" + item.uid); + if ((reg.mWhich & ActivityManager.UID_OBSERVER_GONE) != 0) { + if (DEBUG_UID_OBSERVERS) { + Slog.i(TAG_UID_OBSERVERS, "UID gone uid=" + item.uid); + } observer.onUidGone(item.uid, item.ephemeral); } - if (reg.lastProcStates != null) { - reg.lastProcStates.delete(item.uid); + if (reg.mLastProcStates != null) { + reg.mLastProcStates.delete(item.uid); } } else { - if ((reg.which & ActivityManager.UID_OBSERVER_PROCSTATE) != 0) { - if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, - "UID CHANGED uid=" + item.uid - + ": " + item.processState + ": " + item.capability); + if ((reg.mWhich & ActivityManager.UID_OBSERVER_PROCSTATE) != 0) { + if (DEBUG_UID_OBSERVERS) { + Slog.i(TAG_UID_OBSERVERS, "UID CHANGED uid=" + item.uid + + ": " + item.processState + ": " + item.capability); + } boolean doReport = true; - if (reg.cutpoint >= ActivityManager.MIN_PROCESS_STATE) { - final int lastState = reg.lastProcStates.get(item.uid, + if (reg.mCutpoint >= ActivityManager.MIN_PROCESS_STATE) { + final int lastState = reg.mLastProcStates.get(item.uid, ActivityManager.PROCESS_STATE_UNKNOWN); if (lastState != ActivityManager.PROCESS_STATE_UNKNOWN) { - final boolean lastAboveCut = lastState <= reg.cutpoint; - final boolean newAboveCut = item.processState <= reg.cutpoint; + final boolean lastAboveCut = lastState <= reg.mCutpoint; + final boolean newAboveCut = item.processState <= reg.mCutpoint; doReport = lastAboveCut != newAboveCut; } else { doReport = item.processState != PROCESS_STATE_NONEXISTENT; } } if (doReport) { - if (reg.lastProcStates != null) { - reg.lastProcStates.put(item.uid, item.processState); + if (reg.mLastProcStates != null) { + reg.mLastProcStates.put(item.uid, item.processState); } observer.onUidStateChanged(item.uid, item.processState, item.procStateSeq, item.capability); @@ -311,7 +321,7 @@ public class UidObserverController { } private boolean isEphemeralLocked(int uid) { - String packages[] = mService.mContext.getPackageManager().getPackagesForUid(uid); + final String[] packages = mService.mContext.getPackageManager().getPackagesForUid(uid); if (packages == null || packages.length != 1) { // Ephemeral apps cannot share uid return false; } @@ -321,41 +331,41 @@ public class UidObserverController { @GuardedBy("mService") void dump(PrintWriter pw, String dumpPackage) { - final int NI = mUidObservers.getRegisteredCallbackCount(); + final int count = mUidObservers.getRegisteredCallbackCount(); boolean printed = false; - for (int i=0; i<NI; i++) { + for (int i = 0; i < count; i++) { final UidObserverRegistration reg = (UidObserverRegistration) mUidObservers.getRegisteredCallbackCookie(i); - if (dumpPackage == null || dumpPackage.equals(reg.pkg)) { + if (dumpPackage == null || dumpPackage.equals(reg.mPkg)) { if (!printed) { pw.println(" mUidObservers:"); printed = true; } - pw.print(" "); UserHandle.formatUid(pw, reg.uid); - pw.print(" "); pw.print(reg.pkg); + pw.print(" "); UserHandle.formatUid(pw, reg.mUid); + pw.print(" "); pw.print(reg.mPkg); final IUidObserver observer = mUidObservers.getRegisteredCallbackItem(i); pw.print(" "); pw.print(observer.getClass().getTypeName()); pw.print(":"); - if ((reg.which&ActivityManager.UID_OBSERVER_IDLE) != 0) { + if ((reg.mWhich & ActivityManager.UID_OBSERVER_IDLE) != 0) { pw.print(" IDLE"); } - if ((reg.which&ActivityManager.UID_OBSERVER_ACTIVE) != 0) { - pw.print(" ACT" ); + if ((reg.mWhich & ActivityManager.UID_OBSERVER_ACTIVE) != 0) { + pw.print(" ACT"); } - if ((reg.which&ActivityManager.UID_OBSERVER_GONE) != 0) { + if ((reg.mWhich & ActivityManager.UID_OBSERVER_GONE) != 0) { pw.print(" GONE"); } - if ((reg.which&ActivityManager.UID_OBSERVER_PROCSTATE) != 0) { + if ((reg.mWhich & ActivityManager.UID_OBSERVER_PROCSTATE) != 0) { pw.print(" STATE"); - pw.print(" (cut="); pw.print(reg.cutpoint); + pw.print(" (cut="); pw.print(reg.mCutpoint); pw.print(")"); } pw.println(); - if (reg.lastProcStates != null) { - final int NJ = reg.lastProcStates.size(); - for (int j=0; j<NJ; j++) { + if (reg.mLastProcStates != null) { + final int size = reg.mLastProcStates.size(); + for (int j = 0; j < size; j++) { pw.print(" Last "); - UserHandle.formatUid(pw, reg.lastProcStates.keyAt(j)); - pw.print(": "); pw.println(reg.lastProcStates.valueAt(j)); + UserHandle.formatUid(pw, reg.mLastProcStates.keyAt(j)); + pw.print(": "); pw.println(reg.mLastProcStates.valueAt(j)); } } } @@ -366,8 +376,8 @@ public class UidObserverController { pw.print(mUidChangeDispatchCount); pw.println(); pw.println(" Slow UID dispatches:"); - final int N = mUidObservers.beginBroadcast(); - for (int i = 0; i < N; i++) { + final int size = mUidObservers.beginBroadcast(); + for (int i = 0; i < size; i++) { UidObserverRegistration r = (UidObserverRegistration) mUidObservers.getBroadcastCookie(i); pw.print(" "); @@ -383,21 +393,21 @@ public class UidObserverController { @GuardedBy("mService") void dumpDebug(ProtoOutputStream proto, String dumpPackage) { - final int NI = mUidObservers.getRegisteredCallbackCount(); - for (int i=0; i<NI; i++) { + final int count = mUidObservers.getRegisteredCallbackCount(); + for (int i = 0; i < count; i++) { final UidObserverRegistration reg = (UidObserverRegistration) mUidObservers.getRegisteredCallbackCookie(i); - if (dumpPackage == null || dumpPackage.equals(reg.pkg)) { + if (dumpPackage == null || dumpPackage.equals(reg.mPkg)) { reg.dumpDebug(proto, ActivityManagerServiceDumpProcessesProto.UID_OBSERVERS); } } } - static final class UidObserverRegistration { - final int uid; - final String pkg; - final int which; - final int cutpoint; + private static final class UidObserverRegistration { + final int mUid; + final String mPkg; + final int mWhich; + final int mCutpoint; /** * Total # of callback calls that took more than {@link #SLOW_UID_OBSERVER_THRESHOLD_MS}. @@ -408,49 +418,49 @@ public class UidObserverController { /** Max time it took for each dispatch. */ int mMaxDispatchTime; - final SparseIntArray lastProcStates; + final SparseIntArray mLastProcStates; // Please keep the enum lists in sync - private static int[] ORIG_ENUMS = new int[]{ + private static final int[] ORIG_ENUMS = new int[]{ ActivityManager.UID_OBSERVER_IDLE, ActivityManager.UID_OBSERVER_ACTIVE, ActivityManager.UID_OBSERVER_GONE, ActivityManager.UID_OBSERVER_PROCSTATE, }; - private static int[] PROTO_ENUMS = new int[]{ + private static final int[] PROTO_ENUMS = new int[]{ ActivityManagerProto.UID_OBSERVER_FLAG_IDLE, ActivityManagerProto.UID_OBSERVER_FLAG_ACTIVE, ActivityManagerProto.UID_OBSERVER_FLAG_GONE, ActivityManagerProto.UID_OBSERVER_FLAG_PROCSTATE, }; - UidObserverRegistration(int _uid, String _pkg, int _which, int _cutpoint) { - uid = _uid; - pkg = _pkg; - which = _which; - cutpoint = _cutpoint; + UidObserverRegistration(int uid, String pkg, int which, int cutpoint) { + this.mUid = uid; + this.mPkg = pkg; + this.mWhich = which; + this.mCutpoint = cutpoint; if (cutpoint >= ActivityManager.MIN_PROCESS_STATE) { - lastProcStates = new SparseIntArray(); + mLastProcStates = new SparseIntArray(); } else { - lastProcStates = null; + mLastProcStates = null; } } void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); - proto.write(UidObserverRegistrationProto.UID, uid); - proto.write(UidObserverRegistrationProto.PACKAGE, pkg); + proto.write(UidObserverRegistrationProto.UID, mUid); + proto.write(UidObserverRegistrationProto.PACKAGE, mPkg); ProtoUtils.writeBitWiseFlagsToProtoEnum(proto, UidObserverRegistrationProto.FLAGS, - which, ORIG_ENUMS, PROTO_ENUMS); - proto.write(UidObserverRegistrationProto.CUT_POINT, cutpoint); - if (lastProcStates != null) { - final int NI = lastProcStates.size(); - for (int i=0; i<NI; i++) { + mWhich, ORIG_ENUMS, PROTO_ENUMS); + proto.write(UidObserverRegistrationProto.CUT_POINT, mCutpoint); + if (mLastProcStates != null) { + final int size = mLastProcStates.size(); + for (int i = 0; i < size; i++) { final long pToken = proto.start(UidObserverRegistrationProto.LAST_PROC_STATES); proto.write(UidObserverRegistrationProto.ProcState.UID, - lastProcStates.keyAt(i)); + mLastProcStates.keyAt(i)); proto.write(UidObserverRegistrationProto.ProcState.STATE, - lastProcStates.valueAt(i)); + mLastProcStates.valueAt(i)); proto.end(pToken); } } diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 7420e0a6e828..83bf28e2d3ba 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -988,6 +988,8 @@ class UserController implements Handler.Callback { final ArrayList<IStopUserCallback> stopCallbacks; final ArrayList<KeyEvictedCallback> keyEvictedCallbacks; int userIdToLock = userId; + // Must get a reference to UserInfo before it's removed + final UserInfo userInfo = getUserInfo(userId); synchronized (mLock) { stopCallbacks = new ArrayList<>(uss.mStopCallbacks); keyEvictedCallbacks = new ArrayList<>(uss.mKeyEvictedCallbacks); @@ -1030,8 +1032,8 @@ class UserController implements Handler.Callback { if (stopped) { mInjector.systemServiceManagerCleanupUser(userId); mInjector.stackSupervisorRemoveUser(userId); + // Remove the user if it is ephemeral. - UserInfo userInfo = getUserInfo(userId); if (userInfo.isEphemeral() && !userInfo.preCreated) { mInjector.getUserManager().removeUserEvenWhenDisallowed(userId); } diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java index a47904c40cc3..54c179030929 100644 --- a/services/core/java/com/android/server/biometrics/AuthService.java +++ b/services/core/java/com/android/server/biometrics/AuthService.java @@ -259,17 +259,6 @@ public class AuthService extends SystemService { } @Override - public void resetLockout(int userId, byte[] hardwareAuthToken) throws RemoteException { - checkInternalPermission(); - final long identity = Binder.clearCallingIdentity(); - try { - mBiometricService.resetLockout(userId, hardwareAuthToken); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override public long[] getAuthenticatorIds() throws RemoteException { // In this method, we're not checking whether the caller is permitted to use face // API because current authenticator ID is leaked (in a more contrived way) via Android diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index 382bdbb246a1..3e0a40f9c288 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -638,19 +638,6 @@ public class BiometricService extends SystemService { } @Override // Binder call - public void resetLockout(int userId, byte[] hardwareAuthToken) { - checkInternalPermission(); - - try { - for (BiometricSensor sensor : mSensors) { - sensor.impl.resetLockout(userId, hardwareAuthToken); - } - } catch (RemoteException e) { - Slog.e(TAG, "Remote exception", e); - } - } - - @Override // Binder call public long[] getAuthenticatorIds(int callingUserId) { checkInternalPermission(); diff --git a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java index ab48fdb0fd6e..73fc17aa26f1 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java @@ -45,7 +45,7 @@ public abstract class AcquisitionClient<T> extends ClientMonitor<T> implements I private final PowerManager mPowerManager; private final VibrationEffect mSuccessVibrationEffect; private final VibrationEffect mErrorVibrationEffect; - private boolean mShouldSendErrorToClient; + private boolean mShouldSendErrorToClient = true; private boolean mAlreadyCancelled; /** @@ -85,11 +85,11 @@ public abstract class AcquisitionClient<T> extends ClientMonitor<T> implements I // case (success, failure, or error) is received from the HAL (e.g. versions of fingerprint // that do not handle lockout under the HAL. In these cases, ensure that the framework only // sends errors once per ClientMonitor. - if (!mShouldSendErrorToClient) { + if (mShouldSendErrorToClient) { logOnError(getContext(), errorCode, vendorCode, getTargetUserId()); try { if (getListener() != null) { - mShouldSendErrorToClient = true; + mShouldSendErrorToClient = false; getListener().onError(getSensorId(), getCookie(), errorCode, vendorCode); } } catch (RemoteException e) { @@ -98,7 +98,7 @@ public abstract class AcquisitionClient<T> extends ClientMonitor<T> implements I } if (finish) { - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } @@ -114,7 +114,7 @@ public abstract class AcquisitionClient<T> extends ClientMonitor<T> implements I } @Override - public void cancelWithoutStarting(@NonNull FinishCallback finishCallback) { + public void cancelWithoutStarting(@NonNull Callback callback) { final int errorCode = BiometricConstants.BIOMETRIC_ERROR_CANCELED; try { if (getListener() != null) { @@ -123,7 +123,7 @@ public abstract class AcquisitionClient<T> extends ClientMonitor<T> implements I } catch (RemoteException e) { Slog.w(TAG, "Failed to invoke sendError", e); } - finishCallback.onClientFinished(this, true /* success */); + callback.onClientFinished(this, true /* success */); } /** @@ -155,7 +155,7 @@ public abstract class AcquisitionClient<T> extends ClientMonitor<T> implements I } } catch (RemoteException e) { Slog.w(TAG, "Failed to invoke sendAcquired", e); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java index cb2321f524f6..9128359250df 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java @@ -99,6 +99,14 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T> return getCookie() != 0; } + public long getOperationId() { + return mOperationId; + } + + public boolean isRestricted() { + return mIsRestricted; + } + @Override protected boolean isCryptoOperation() { return mOperationId != 0; @@ -191,7 +199,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T> } } catch (RemoteException e) { Slog.e(TAG, "Unable to notify listener, finishing", e); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } @@ -211,8 +219,8 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T> * Start authentication */ @Override - public void start(@NonNull FinishCallback finishCallback) { - super.start(finishCallback); + public void start(@NonNull Callback callback) { + super.start(callback); final @LockoutTracker.LockoutMode int lockoutMode = mLockoutTracker.getLockoutModeForUser(getTargetUserId()); diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java index 4f37dccea42e..588e865112c2 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java @@ -85,7 +85,7 @@ public class BiometricScheduler { static final int STATE_WAITING_FOR_COOKIE = 4; /** - * The {@link ClientMonitor.FinishCallback} has been invoked and the client is finished. + * The {@link ClientMonitor.Callback} has been invoked and the client is finished. */ static final int STATE_FINISHED = 5; @@ -99,13 +99,13 @@ public class BiometricScheduler { @interface OperationState {} @NonNull final ClientMonitor<?> clientMonitor; - @Nullable final ClientMonitor.FinishCallback clientFinishCallback; + @Nullable final ClientMonitor.Callback mClientCallback; @OperationState int state; Operation(@NonNull ClientMonitor<?> clientMonitor, - @Nullable ClientMonitor.FinishCallback finishCallback) { + @Nullable ClientMonitor.Callback callback) { this.clientMonitor = clientMonitor; - this.clientFinishCallback = finishCallback; + this.mClientCallback = callback; state = STATE_WAITING_IN_QUEUE; } @@ -133,7 +133,7 @@ public class BiometricScheduler { public void run() { if (operation.state != Operation.STATE_FINISHED) { Slog.e(tag, "[Watchdog Triggered]: " + operation); - operation.clientMonitor.mFinishCallback + operation.clientMonitor.mCallback .onClientFinished(operation.clientMonitor, false /* success */); } } @@ -175,17 +175,25 @@ public class BiometricScheduler { @Nullable private final GestureAvailabilityDispatcher mGestureAvailabilityDispatcher; @NonNull private final IBiometricService mBiometricService; @NonNull private final Handler mHandler = new Handler(Looper.getMainLooper()); - @NonNull private final InternalFinishCallback mInternalFinishCallback; + @NonNull private final InternalCallback mInternalCallback; @NonNull private final Queue<Operation> mPendingOperations; @Nullable private Operation mCurrentOperation; @NonNull private final ArrayDeque<CrashState> mCrashStates; - // Internal finish callback, notified when an operation is complete. Notifies the requester + // Internal callback, notified when an operation is complete. Notifies the requester // that the operation is complete, before performing internal scheduler work (such as // starting the next client). - private class InternalFinishCallback implements ClientMonitor.FinishCallback { + public class InternalCallback implements ClientMonitor.Callback { @Override - public void onClientFinished(ClientMonitor<?> clientMonitor, boolean success) { + public void onClientStarted(@NonNull ClientMonitor<?> clientMonitor) { + Slog.d(getTag(), "[Started] " + clientMonitor); + if (mCurrentOperation.mClientCallback != null) { + mCurrentOperation.mClientCallback.onClientStarted(clientMonitor); + } + } + + @Override + public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, boolean success) { mHandler.post(() -> { if (mCurrentOperation == null) { Slog.e(getTag(), "[Finishing] " + clientMonitor @@ -203,8 +211,8 @@ public class BiometricScheduler { Slog.d(getTag(), "[Finishing] " + clientMonitor + ", success: " + success); mCurrentOperation.state = Operation.STATE_FINISHED; - if (mCurrentOperation.clientFinishCallback != null) { - mCurrentOperation.clientFinishCallback.onClientFinished(clientMonitor, success); + if (mCurrentOperation.mClientCallback != null) { + mCurrentOperation.mClientCallback.onClientFinished(clientMonitor, success); } if (mGestureAvailabilityDispatcher != null) { @@ -227,7 +235,7 @@ public class BiometricScheduler { public BiometricScheduler(@NonNull String tag, @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { mBiometricTag = tag; - mInternalFinishCallback = new InternalFinishCallback(); + mInternalCallback = new InternalCallback(); mGestureAvailabilityDispatcher = gestureAvailabilityDispatcher; mPendingOperations = new ArrayDeque<>(); mBiometricService = IBiometricService.Stub.asInterface( @@ -235,6 +243,14 @@ public class BiometricScheduler { mCrashStates = new ArrayDeque<>(); } + /** + * @return A reference to the internal callback that should be invoked whenever the scheduler + * needs to (e.g. client started, client finished). + */ + @NonNull protected InternalCallback getInternalCallback() { + return mInternalCallback; + } + private String getTag() { return BASE_TAG + "/" + mBiometricTag; } @@ -262,7 +278,7 @@ public class BiometricScheduler { } final Interruptable interruptable = (Interruptable) currentClient; - interruptable.cancelWithoutStarting(mInternalFinishCallback); + interruptable.cancelWithoutStarting(getInternalCallback()); // Now we wait for the client to send its FinishCallback, which kicks off the next // operation. return; @@ -280,7 +296,7 @@ public class BiometricScheduler { final boolean shouldStartNow = currentClient.getCookie() == 0; if (shouldStartNow) { Slog.d(getTag(), "[Starting] " + mCurrentOperation); - currentClient.start(mInternalFinishCallback); + currentClient.start(getInternalCallback()); mCurrentOperation.state = Operation.STATE_STARTED; } else { try { @@ -324,7 +340,7 @@ public class BiometricScheduler { Slog.d(getTag(), "[Starting] Prepared client: " + mCurrentOperation); mCurrentOperation.state = Operation.STATE_STARTED; - mCurrentOperation.clientMonitor.start(mInternalFinishCallback); + mCurrentOperation.clientMonitor.start(getInternalCallback()); } /** @@ -340,11 +356,11 @@ public class BiometricScheduler { * Adds a {@link ClientMonitor} to the pending queue * * @param clientMonitor operation to be scheduled - * @param clientFinishCallback optional callback, invoked when the client is finished, but + * @param clientCallback optional callback, invoked when the client is finished, but * before it has been removed from the queue. */ public void scheduleClientMonitor(@NonNull ClientMonitor<?> clientMonitor, - @Nullable ClientMonitor.FinishCallback clientFinishCallback) { + @Nullable ClientMonitor.Callback clientCallback) { // Mark any interruptable pending clients as canceling. Once they reach the head of the // queue, the scheduler will send ERROR_CANCELED and skip the operation. for (Operation operation : mPendingOperations) { @@ -356,7 +372,7 @@ public class BiometricScheduler { } } - mPendingOperations.add(new Operation(clientMonitor, clientFinishCallback)); + mPendingOperations.add(new Operation(clientMonitor, clientCallback)); Slog.d(getTag(), "[Added] " + clientMonitor + ", new queue size: " + mPendingOperations.size()); diff --git a/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java index 8b27781940ac..dec40e39fb29 100644 --- a/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java +++ b/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java @@ -42,7 +42,15 @@ public abstract class ClientMonitor<T> extends LoggableMonitor implements IBinde /** * Interface that ClientMonitor holders should use to receive callbacks. */ - public interface FinishCallback { + public interface Callback { + /** + * Invoked when the ClientMonitor operation has been started (e.g. reached the head of + * the queue and becomes the current operation). + * + * @param clientMonitor Reference of the ClientMonitor that is starting. + */ + default void onClientStarted(@NonNull ClientMonitor<?> clientMonitor) {} + /** * Invoked when the ClientMonitor operation is complete. This abstracts away asynchronous * (i.e. Authenticate, Enroll, Enumerate, Remove) and synchronous (i.e. generateChallenge, @@ -52,7 +60,7 @@ public abstract class ClientMonitor<T> extends LoggableMonitor implements IBinde * @param clientMonitor Reference of the ClientMonitor that finished. * @param success True if the operation completed successfully. */ - void onClientFinished(ClientMonitor<?> clientMonitor, boolean success); + default void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, boolean success) {} } /** @@ -79,7 +87,7 @@ public abstract class ClientMonitor<T> extends LoggableMonitor implements IBinde private final int mCookie; boolean mAlreadyDone; - @NonNull protected FinishCallback mFinishCallback; + @NonNull protected Callback mCallback; /** * @param context system_server context @@ -125,17 +133,18 @@ public abstract class ClientMonitor<T> extends LoggableMonitor implements IBinde /** * Invoked if the scheduler is unable to start the ClientMonitor (for example the HAL is null). * If such a problem is detected, the scheduler will not invoke - * {@link #start(FinishCallback)}. + * {@link #start(Callback)}. */ public abstract void unableToStart(); /** * Starts the ClientMonitor's lifecycle. Invokes {@link #startHalOperation()} when internal book * keeping is complete. - * @param finishCallback invoked when the operation is complete (succeeds, fails, etc) + * @param callback invoked when the operation is complete (succeeds, fails, etc) */ - public void start(@NonNull FinishCallback finishCallback) { - mFinishCallback = finishCallback; + public void start(@NonNull Callback callback) { + mCallback = callback; + mCallback.onClientStarted(this); } /** diff --git a/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java b/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java index 3cef6667b644..cb7db92ee132 100644 --- a/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java +++ b/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java @@ -128,11 +128,11 @@ public final class ClientMonitorCallbackConverter { } } - public void onChallengeGenerated(long challenge) throws RemoteException { + public void onChallengeGenerated(int sensorId, long challenge) throws RemoteException { if (mFaceServiceReceiver != null) { - mFaceServiceReceiver.onChallengeGenerated(challenge); + mFaceServiceReceiver.onChallengeGenerated(sensorId, challenge); } else if (mFingerprintServiceReceiver != null) { - mFingerprintServiceReceiver.onChallengeGenerated(challenge); + mFingerprintServiceReceiver.onChallengeGenerated(sensorId, challenge); } } @@ -142,10 +142,21 @@ public final class ClientMonitorCallbackConverter { } } - public void onFeatureGet(boolean success, int feature, boolean value) - throws RemoteException { + public void onFeatureGet(boolean success, int feature, boolean value) throws RemoteException { if (mFaceServiceReceiver != null) { mFaceServiceReceiver.onFeatureGet(success, feature, value); } } + + public void onChallengeInterrupted(int sensorId) throws RemoteException { + if (mFaceServiceReceiver != null) { + mFaceServiceReceiver.onChallengeInterrupted(sensorId); + } + } + + public void onChallengeInterruptFinished(int sensorId) throws RemoteException { + if (mFaceServiceReceiver != null) { + mFaceServiceReceiver.onChallengeInterruptFinished(sensorId); + } + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java index add5829c1342..8bf9680d60cd 100644 --- a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java @@ -77,18 +77,18 @@ public abstract class EnrollClient<T> extends AcquisitionClient<T> { mBiometricUtils.addBiometricForUser(getContext(), getTargetUserId(), identifier); logOnEnrolled(getTargetUserId(), System.currentTimeMillis() - mEnrollmentStartTimeMs, true /* enrollSuccessful */); - mFinishCallback.onClientFinished(this, true /* success */); + mCallback.onClientFinished(this, true /* success */); } notifyUserActivity(); } @Override - public void start(@NonNull FinishCallback finishCallback) { - super.start(finishCallback); + public void start(@NonNull Callback callback) { + super.start(callback); if (hasReachedEnrollmentLimit()) { Slog.e(TAG, "Reached enrollment limit"); - finishCallback.onClientFinished(this, false /* success */); + callback.onClientFinished(this, false /* success */); return; } diff --git a/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java index dad5cad1ed8d..92c498c55dbf 100644 --- a/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java @@ -40,23 +40,23 @@ public abstract class GenerateChallengeClient<T> extends ClientMonitor<T> { @Override public void unableToStart() { try { - getListener().onChallengeGenerated(0L); + getListener().onChallengeGenerated(getSensorId(), 0L); } catch (RemoteException e) { Slog.e(TAG, "Unable to send error", e); } } @Override - public void start(@NonNull FinishCallback finishCallback) { - super.start(finishCallback); + public void start(@NonNull Callback callback) { + super.start(callback); startHalOperation(); try { - getListener().onChallengeGenerated(mChallenge); - mFinishCallback.onClientFinished(this, true /* success */); + getListener().onChallengeGenerated(getSensorId(), mChallenge); + mCallback.onClientFinished(this, true /* success */); } catch (RemoteException e) { Slog.e(TAG, "Remote exception", e); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } } diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java index 6d7b0fd3d5f1..5c08bce9b44f 100644 --- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java @@ -62,29 +62,35 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide private final List<S> mEnrolledList; private ClientMonitor<T> mCurrentTask; - private final FinishCallback mEnumerateFinishCallback = (clientMonitor, success) -> { - final List<BiometricAuthenticator.Identifier> unknownHALTemplates = - ((InternalEnumerateClient<T>) mCurrentTask).getUnknownHALTemplates(); - - if (!unknownHALTemplates.isEmpty()) { - Slog.w(TAG, "Adding " + unknownHALTemplates.size() + " templates for deletion"); - } - for (BiometricAuthenticator.Identifier unknownHALTemplate : unknownHALTemplates) { - mUnknownHALTemplates.add(new UserTemplate(unknownHALTemplate, - mCurrentTask.getTargetUserId())); - } - - if (mUnknownHALTemplates.isEmpty()) { - // No unknown HAL templates. Unknown framework templates are already cleaned up in - // InternalEnumerateClient. Finish this client. - mFinishCallback.onClientFinished(this, success); - } else { - startCleanupUnknownHalTemplates(); + private final Callback mEnumerateCallback = new Callback() { + @Override + public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, boolean success) { + final List<BiometricAuthenticator.Identifier> unknownHALTemplates = + ((InternalEnumerateClient<T>) mCurrentTask).getUnknownHALTemplates(); + + if (!unknownHALTemplates.isEmpty()) { + Slog.w(TAG, "Adding " + unknownHALTemplates.size() + " templates for deletion"); + } + for (BiometricAuthenticator.Identifier unknownHALTemplate : unknownHALTemplates) { + mUnknownHALTemplates.add(new UserTemplate(unknownHALTemplate, + mCurrentTask.getTargetUserId())); + } + + if (mUnknownHALTemplates.isEmpty()) { + // No unknown HAL templates. Unknown framework templates are already cleaned up in + // InternalEnumerateClient. Finish this client. + mCallback.onClientFinished(InternalCleanupClient.this, success); + } else { + startCleanupUnknownHalTemplates(); + } } }; - private final FinishCallback mRemoveFinishCallback = (clientMonitor, success) -> { - mFinishCallback.onClientFinished(this, success); + private final Callback mRemoveCallback = new Callback() { + @Override + public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, boolean success) { + mCallback.onClientFinished(InternalCleanupClient.this, success); + } }; protected abstract InternalEnumerateClient<T> getEnumerateClient(Context context, @@ -116,7 +122,7 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, mStatsModality, BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL); - mCurrentTask.start(mRemoveFinishCallback); + mCurrentTask.start(mRemoveCallback); } @Override @@ -125,13 +131,13 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide } @Override - public void start(@NonNull FinishCallback finishCallback) { - super.start(finishCallback); + public void start(@NonNull Callback callback) { + super.start(callback); // Start enumeration. Removal will start if necessary, when enumeration is completed. mCurrentTask = getEnumerateClient(getContext(), mLazyDaemon, getToken(), getTargetUserId(), getOwnerString(), mEnrolledList, mBiometricUtils, getSensorId()); - mCurrentTask.start(mEnumerateFinishCallback); + mCurrentTask.start(mEnumerateCallback); } @Override @@ -147,7 +153,7 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide + mCurrentTask.getClass().getSimpleName()); return; } - ((RemovalClient) mCurrentTask).onRemoved(identifier, remaining); + ((RemovalClient<T>) mCurrentTask).onRemoved(identifier, remaining); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java index 3f73cd56e6c3..e07f71298d13 100644 --- a/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java @@ -62,7 +62,7 @@ public abstract class InternalEnumerateClient<T> extends ClientMonitor<T> handleEnumeratedTemplate(identifier); if (remaining == 0) { doTemplateCleanup(); - mFinishCallback.onClientFinished(this, true /* success */); + mCallback.onClientFinished(this, true /* success */); } } @@ -72,8 +72,8 @@ public abstract class InternalEnumerateClient<T> extends ClientMonitor<T> } @Override - public void start(@NonNull FinishCallback finishCallback) { - super.start(finishCallback); + public void start(@NonNull Callback callback) { + super.start(callback); // The biometric template ids will be removed when we get confirmation from the HAL startHalOperation(); diff --git a/services/core/java/com/android/server/biometrics/sensors/Interruptable.java b/services/core/java/com/android/server/biometrics/sensors/Interruptable.java index 35d917747574..28e0117afd36 100644 --- a/services/core/java/com/android/server/biometrics/sensors/Interruptable.java +++ b/services/core/java/com/android/server/biometrics/sensors/Interruptable.java @@ -37,10 +37,10 @@ public interface Interruptable { /** * Notifies the client that it needs to finish before - * {@link ClientMonitor#start(ClientMonitor.FinishCallback)} was invoked. This usually happens + * {@link ClientMonitor#start(ClientMonitor.Callback)} was invoked. This usually happens * if the client is still waiting in the pending queue and got notified that a subsequent * operation is preempting it. - * @param finishCallback invoked when the operation is completed. + * @param callback invoked when the operation is completed. */ - void cancelWithoutStarting(@NonNull ClientMonitor.FinishCallback finishCallback); + void cancelWithoutStarting(@NonNull ClientMonitor.Callback callback); } diff --git a/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java b/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java index 1a4216f9d43c..d85ab25cc812 100644 --- a/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java +++ b/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java @@ -58,6 +58,10 @@ public abstract class LoggableMonitor { mStatsClient = statsClient; } + public int getStatsClient() { + return mStatsClient; + } + private boolean isAnyFieldUnknown() { return mStatsModality == BiometricsProtoEnums.MODALITY_UNKNOWN || mStatsAction == BiometricsProtoEnums.ACTION_UNKNOWN diff --git a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java index 1c49bcdbadf4..1348f797a2dc 100644 --- a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java @@ -55,8 +55,8 @@ public abstract class RemovalClient<T> extends ClientMonitor<T> implements Remov } @Override - public void start(@NonNull FinishCallback finishCallback) { - super.start(finishCallback); + public void start(@NonNull Callback callback) { + super.start(callback); // The biometric template ids will be removed when we get confirmation from the HAL startHalOperation(); @@ -85,7 +85,7 @@ public abstract class RemovalClient<T> extends ClientMonitor<T> implements Remov // cleanup). mAuthenticatorIds.put(getTargetUserId(), 0L); } - mFinishCallback.onClientFinished(this, true /* success */); + mCallback.onClientFinished(this, true /* success */); } } } diff --git a/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java index b78ee49826f2..5deb8fa26639 100644 --- a/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java @@ -36,10 +36,10 @@ public abstract class RevokeChallengeClient<T> extends ClientMonitor<T> { } @Override - public void start(@NonNull FinishCallback finishCallback) { - super.start(finishCallback); + public void start(@NonNull Callback callback) { + super.start(callback); startHalOperation(); - mFinishCallback.onClientFinished(this, true /* success */); + mCallback.onClientFinished(this, true /* success */); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java index 6c57208c1e84..7dd6217016eb 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java @@ -29,6 +29,7 @@ import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.face.V1_0.IBiometricsFace; import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback; import android.hardware.face.Face; +import android.hardware.face.FaceManager; import android.hardware.face.FaceSensorProperties; import android.hardware.face.IFaceServiceReceiver; import android.os.Build; @@ -98,6 +99,11 @@ class Face10 implements IHwBinder.DeathRecipient { @Nullable private IBiometricsFace mDaemon; private int mCurrentUserId = UserHandle.USER_NULL; + // If a challenge is generated, keep track of its owner. Since IBiometricsFace@1.0 only + // supports a single in-flight challenge, we must notify the interrupted owner that its + // challenge is no longer valid. The interrupted owner will be notified when the interrupter + // has finished. + @Nullable private FaceGenerateChallengeClient mCurrentChallengeOwner; private final UserSwitchObserver mUserSwitchObserver = new SynchronousUserSwitchObserver() { @Override @@ -394,9 +400,12 @@ class Face10 implements IHwBinder.DeathRecipient { final FaceUpdateActiveUserClient client = new FaceUpdateActiveUserClient(mContext, mLazyDaemon, targetUserId, mContext.getOpPackageName(), mSensorId, mCurrentUserId, hasEnrolled, mAuthenticatorIds); - mScheduler.scheduleClientMonitor(client, (clientMonitor, success) -> { - if (success) { - mCurrentUserId = targetUserId; + mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() { + @Override + public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, boolean success) { + if (success) { + mCurrentUserId = targetUserId; + } } }); } @@ -456,21 +465,87 @@ class Face10 implements IHwBinder.DeathRecipient { }); } + /** + * {@link IBiometricsFace} only supports a single in-flight challenge. In cases where two + * callers both need challenges (e.g. resetLockout right before enrollment), we need to ensure + * that either: + * 1) generateChallenge/operation/revokeChallenge is complete before the next generateChallenge + * is processed by the scheduler, or + * 2) the generateChallenge callback provides a mechanism for notifying the caller that its + * challenge has been invalidated by a subsequent caller, as well as a mechanism for + * notifying the previous caller that the interrupting operation is complete (e.g. the + * interrupting client's challenge has been revoked, so that the interrupted client can + * start retry logic if necessary). See + * {@link FaceManager.GenerateChallengeCallback#onChallengeInterruptFinished(int)} + * The only case of conflicting challenges is currently resetLockout --> enroll. So, the second + * option seems better as it prioritizes the new operation, which is user-facing. + */ void scheduleGenerateChallenge(@NonNull IBinder token, @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) { mHandler.post(() -> { + if (mCurrentChallengeOwner != null) { + Slog.w(TAG, "Current challenge owner: " + mCurrentChallengeOwner + + ", interrupted by: " + opPackageName); + try { + mCurrentChallengeOwner.getListener().onChallengeInterrupted(mSensorId); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to notify challenge interrupted", e); + } + } + final FaceGenerateChallengeClient client = new FaceGenerateChallengeClient(mContext, mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), opPackageName, - mSensorId); - mScheduler.scheduleClientMonitor(client); + mSensorId, mCurrentChallengeOwner); + mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() { + @Override + public void onClientStarted(@NonNull ClientMonitor<?> clientMonitor) { + if (client != clientMonitor) { + Slog.e(TAG, "scheduleGenerateChallenge, mismatched client." + + " Expecting: " + client + ", received: " + clientMonitor); + return; + } + Slog.d(TAG, "Current challenge owner: " + client); + mCurrentChallengeOwner = client; + } + }); }); } void scheduleRevokeChallenge(@NonNull IBinder token, @NonNull String owner) { mHandler.post(() -> { + if (!mCurrentChallengeOwner.getOwnerString().contentEquals(owner)) { + Slog.e(TAG, "scheduleRevokeChallenge, package: " + owner + + " attempting to revoke challenge owned by: " + + mCurrentChallengeOwner.getOwnerString()); + return; + } + final FaceRevokeChallengeClient client = new FaceRevokeChallengeClient(mContext, mLazyDaemon, token, owner, mSensorId); - mScheduler.scheduleClientMonitor(client); + mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() { + @Override + public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, + boolean success) { + if (client != clientMonitor) { + Slog.e(TAG, "scheduleRevokeChallenge, mismatched client." + + "Expecting: " + client + ", received: " + clientMonitor); + return; + } + + final FaceGenerateChallengeClient previousChallengeOwner = + mCurrentChallengeOwner.getInterruptedClient(); + mCurrentChallengeOwner = null; + Slog.d(TAG, "Previous challenge owner: " + previousChallengeOwner); + if (previousChallengeOwner != null) { + try { + previousChallengeOwner.getListener() + .onChallengeInterruptFinished(mSensorId); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to notify interrupt finished", e); + } + } + } + }); }); } @@ -488,12 +563,16 @@ class Face10 implements IHwBinder.DeathRecipient { opPackageName, FaceUtils.getInstance(), disabledFeatures, ENROLL_TIMEOUT_SEC, surfaceHandle, mSensorId); - mScheduler.scheduleClientMonitor(client, ((clientMonitor, success) -> { - if (success) { - // Update authenticatorIds - scheduleUpdateActiveUserWithoutHandler(client.getTargetUserId()); + mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() { + @Override + public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, + boolean success) { + if (success) { + // Update authenticatorIds + scheduleUpdateActiveUserWithoutHandler(client.getTargetUserId()); + } } - })); + }); }); } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticationClient.java index 21bda74bc6b9..892d6a48488d 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticationClient.java @@ -92,7 +92,7 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> { } catch (RemoteException e) { Slog.e(TAG, "Remote exception when requesting auth", e); onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } @@ -103,7 +103,7 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> { } catch (RemoteException e) { Slog.e(TAG, "Remote exception when requesting cancel", e); onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } @@ -131,7 +131,7 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> { // 1) Authenticated == true // 2) Error occurred // 3) Authenticated == false - mFinishCallback.onClientFinished(this, true /* success */); + mCallback.onClientFinished(this, true /* success */); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java index 33244b8e61a8..bbee6cde4603 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java @@ -75,11 +75,6 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub { } @Override - public void resetLockout(int userId, byte[] hardwareAuthToken) throws RemoteException { - mFaceService.resetLockout(userId, hardwareAuthToken); - } - - @Override public long getAuthenticatorId(int callingUserId) throws RemoteException { return mFaceService.getAuthenticatorId(callingUserId); } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceEnrollClient.java index 52a822675c2f..3e843cae96fd 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceEnrollClient.java @@ -116,12 +116,12 @@ public class FaceEnrollClient extends EnrollClient<IBiometricsFace> { } if (status != Status.OK) { onError(BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS, 0 /* vendorCode */); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } catch (RemoteException e) { Slog.e(TAG, "Remote exception when requesting enroll", e); onError(BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS, 0 /* vendorCode */); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } @@ -132,7 +132,7 @@ public class FaceEnrollClient extends EnrollClient<IBiometricsFace> { } catch (RemoteException e) { Slog.e(TAG, "Remote exception when requesting cancel", e); onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceGenerateChallengeClient.java index 67f2712d0b9d..ba401f255e43 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceGenerateChallengeClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceGenerateChallengeClient.java @@ -17,12 +17,14 @@ package com.android.server.biometrics.sensors.face; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.hardware.biometrics.face.V1_0.IBiometricsFace; import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.sensors.ClientMonitor; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.GenerateChallengeClient; @@ -36,10 +38,22 @@ public class FaceGenerateChallengeClient extends GenerateChallengeClient<IBiomet private static final String TAG = "FaceGenerateChallengeClient"; private static final int CHALLENGE_TIMEOUT_SEC = 600; // 10 minutes + // If `this` FaceGenerateChallengeClient was invoked while an existing in-flight challenge + // was not revoked yet, store a reference to the interrupted client here. Notify the interrupted + // client when `this` challenge is revoked. + @Nullable private final FaceGenerateChallengeClient mInterruptedClient; + FaceGenerateChallengeClient(@NonNull Context context, @NonNull LazyDaemon<IBiometricsFace> lazyDaemon, @NonNull IBinder token, - @NonNull ClientMonitorCallbackConverter listener, @NonNull String owner, int sensorId) { + @NonNull ClientMonitorCallbackConverter listener, @NonNull String owner, int sensorId, + @Nullable FaceGenerateChallengeClient interruptedClient) { super(context, lazyDaemon, token, listener, owner, sensorId); + mInterruptedClient = interruptedClient; + } + + @Nullable + public FaceGenerateChallengeClient getInterruptedClient() { + return mInterruptedClient; } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java index ce57cb7686ed..8c7b99d6eb52 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java @@ -61,8 +61,8 @@ public class FaceGetFeatureClient extends ClientMonitor<IBiometricsFace> { } @Override - public void start(@NonNull FinishCallback finishCallback) { - super.start(finishCallback); + public void start(@NonNull Callback callback) { + super.start(callback); startHalOperation(); } @@ -71,10 +71,10 @@ public class FaceGetFeatureClient extends ClientMonitor<IBiometricsFace> { try { final OptionalBool result = getFreshDaemon().getFeature(mFeature, mFaceId); getListener().onFeatureGet(result.status == Status.OK, mFeature, result.value); - mFinishCallback.onClientFinished(this, true /* success */); + mCallback.onClientFinished(this, true /* success */); } catch (RemoteException e) { Slog.e(TAG, "Unable to getFeature", e); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceInternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceInternalEnumerateClient.java index f25242ee9b85..32d48321428a 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceInternalEnumerateClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceInternalEnumerateClient.java @@ -52,7 +52,7 @@ class FaceInternalEnumerateClient extends InternalEnumerateClient<IBiometricsFac getFreshDaemon().enumerate(); } catch (RemoteException e) { Slog.e(TAG, "Remote exception when requesting enumerate", e); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceRemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceRemovalClient.java index 00d5f500b241..dde5ababd6c0 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceRemovalClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceRemovalClient.java @@ -51,7 +51,7 @@ class FaceRemovalClient extends RemovalClient<IBiometricsFace> { getFreshDaemon().remove(mBiometricId); } catch (RemoteException e) { Slog.e(TAG, "Remote exception when requesting remove", e); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceResetLockoutClient.java index 69070da0491e..f4324bedb4c6 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceResetLockoutClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceResetLockoutClient.java @@ -56,8 +56,8 @@ public class FaceResetLockoutClient extends ClientMonitor<IBiometricsFace> { } @Override - public void start(@NonNull FinishCallback finishCallback) { - super.start(finishCallback); + public void start(@NonNull Callback callback) { + super.start(callback); startHalOperation(); } @@ -65,10 +65,10 @@ public class FaceResetLockoutClient extends ClientMonitor<IBiometricsFace> { protected void startHalOperation() { try { getFreshDaemon().resetLockout(mHardwareAuthToken); - mFinishCallback.onClientFinished(this, true /* success */); + mCallback.onClientFinished(this, true /* success */); } catch (RemoteException e) { Slog.e(TAG, "Unable to reset lockout", e); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java index b832a09f8f88..b689106bbc44 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java @@ -80,16 +80,27 @@ public class FaceService extends SystemService { } @Override // Binder call - public void generateChallenge(IBinder token, IFaceServiceReceiver receiver, + public void generateChallenge(IBinder token, int sensorId, IFaceServiceReceiver receiver, String opPackageName) { Utils.checkPermission(getContext(), MANAGE_BIOMETRIC); - mFace10.scheduleGenerateChallenge(token, receiver, opPackageName); + if (sensorId == mFace10.getFaceSensorProperties().sensorId) { + mFace10.scheduleGenerateChallenge(token, receiver, opPackageName); + return; + } + + Slog.w(TAG, "No matching sensor for generateChallenge, sensorId: " + sensorId); } @Override // Binder call - public void revokeChallenge(IBinder token, String owner) { + public void revokeChallenge(IBinder token, int sensorId, String owner) { Utils.checkPermission(getContext(), MANAGE_BIOMETRIC); - mFace10.scheduleRevokeChallenge(token, owner); + + if (sensorId == mFace10.getFaceSensorProperties().sensorId) { + mFace10.scheduleRevokeChallenge(token, owner); + return; + } + + Slog.w(TAG, "No matching sensor for revokeChallenge, sensorId: " + sensorId); } @Override // Binder call @@ -267,9 +278,16 @@ public class FaceService extends SystemService { } @Override // Binder call - public void resetLockout(int userId, byte[] hardwareAuthToken) { + public void resetLockout(IBinder token, int sensorId, int userId, byte[] hardwareAuthToken, + String opPackageName) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); - mFace10.scheduleResetLockout(userId, hardwareAuthToken); + + if (sensorId == mFace10.getFaceSensorProperties().sensorId) { + mFace10.scheduleResetLockout(userId, hardwareAuthToken); + return; + } + + Slog.w(TAG, "No matching sensor for resetLockout, sensorId: " + sensorId); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceSetFeatureClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceSetFeatureClient.java index e7d041a11ccb..94abb7f378df 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceSetFeatureClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceSetFeatureClient.java @@ -70,8 +70,8 @@ public class FaceSetFeatureClient extends ClientMonitor<IBiometricsFace> { } @Override - public void start(@NonNull FinishCallback finishCallback) { - super.start(finishCallback); + public void start(@NonNull Callback callback) { + super.start(callback); startHalOperation(); } @@ -82,10 +82,10 @@ public class FaceSetFeatureClient extends ClientMonitor<IBiometricsFace> { final int result = getFreshDaemon() .setFeature(mFeature, mEnabled, mHardwareAuthToken, mFaceId); getListener().onFeatureSet(result == Status.OK, mFeature); - mFinishCallback.onClientFinished(this, true /* success */); + mCallback.onClientFinished(this, true /* success */); } catch (RemoteException e) { Slog.e(TAG, "Unable to set feature: " + mFeature + " to enabled: " + mEnabled, e); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceUpdateActiveUserClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceUpdateActiveUserClient.java index bcf304e47816..05b176d28e28 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceUpdateActiveUserClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceUpdateActiveUserClient.java @@ -50,8 +50,8 @@ public class FaceUpdateActiveUserClient extends ClientMonitor<IBiometricsFace> { } @Override - public void start(@NonNull FinishCallback finishCallback) { - super.start(finishCallback); + public void start(@NonNull Callback callback) { + super.start(callback); if (mCurrentUserId == getTargetUserId()) { Slog.d(TAG, "Already user: " + mCurrentUserId + ", refreshing authenticatorId"); @@ -61,7 +61,7 @@ public class FaceUpdateActiveUserClient extends ClientMonitor<IBiometricsFace> { } catch (RemoteException e) { Slog.e(TAG, "Unable to refresh authenticatorId", e); } - finishCallback.onClientFinished(this, true /* success */); + callback.onClientFinished(this, true /* success */); return; } @@ -79,16 +79,16 @@ public class FaceUpdateActiveUserClient extends ClientMonitor<IBiometricsFace> { FACE_DATA_DIR); if (!storePath.exists()) { Slog.e(TAG, "vold has not created the directory?"); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); return; } try { getFreshDaemon().setActiveUser(getTargetUserId(), storePath.getAbsolutePath()); - mFinishCallback.onClientFinished(this, true /* success */); + mCallback.onClientFinished(this, true /* success */); } catch (RemoteException e) { Slog.e(TAG, "Failed to setActiveUser: " + e); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java index dad038626762..c5c28227fd24 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java @@ -84,7 +84,7 @@ class Fingerprint21 implements IHwBinder.DeathRecipient { private static final String TAG = "Fingerprint21"; private static final int ENROLL_TIMEOUT_SEC = 60; - private final Context mContext; + final Context mContext; private final IActivityTaskManager mActivityTaskManager; private final FingerprintSensorProperties mSensorProperties; private final BiometricScheduler mScheduler; @@ -96,6 +96,7 @@ class Fingerprint21 implements IHwBinder.DeathRecipient { private final Map<Integer, Long> mAuthenticatorIds; @Nullable private IBiometricsFingerprint mDaemon; + @NonNull private final HalResultController mHalResultController; @Nullable private IUdfpsOverlayController mUdfpsOverlayController; private int mCurrentUserId = UserHandle.USER_NULL; @@ -146,15 +147,37 @@ class Fingerprint21 implements IHwBinder.DeathRecipient { } }; - private final IBiometricsFingerprintClientCallback mDaemonCallback = - new IBiometricsFingerprintClientCallback.Stub() { + public static class HalResultController extends IBiometricsFingerprintClientCallback.Stub { + + /** + * Interface to sends results to the HalResultController's owner. + */ + public interface Callback { + /** + * Invoked when the HAL sends ERROR_HW_UNAVAILABLE. + */ + void onHardwareUnavailable(); + } + + @NonNull private final Context mContext; + @NonNull final Handler mHandler; + @NonNull final BiometricScheduler mScheduler; + @Nullable private Callback mCallback; + + HalResultController(@NonNull Context context, @NonNull Handler handler, + @NonNull BiometricScheduler scheduler) { + mContext = context; + mHandler = handler; + mScheduler = scheduler; + } + + public void setCallback(@Nullable Callback callback) { + mCallback = callback; + } + @Override public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) { mHandler.post(() -> { - final CharSequence name = FingerprintUtils.getInstance() - .getUniqueName(mContext, mCurrentUserId); - final Fingerprint fingerprint = new Fingerprint(name, groupId, fingerId, deviceId); - final ClientMonitor<?> client = mScheduler.getCurrentClient(); if (!(client instanceof FingerprintEnrollClient)) { Slog.e(TAG, "onEnrollResult for non-enroll client: " @@ -162,6 +185,11 @@ class Fingerprint21 implements IHwBinder.DeathRecipient { return; } + final int currentUserId = client.getTargetUserId(); + final CharSequence name = FingerprintUtils.getInstance() + .getUniqueName(mContext, currentUserId); + final Fingerprint fingerprint = new Fingerprint(name, groupId, fingerId, deviceId); + final FingerprintEnrollClient enrollClient = (FingerprintEnrollClient) client; enrollClient.onEnrollResult(fingerprint, remaining); }); @@ -224,8 +252,9 @@ class Fingerprint21 implements IHwBinder.DeathRecipient { if (error == BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE) { Slog.e(TAG, "Got ERROR_HW_UNAVAILABLE"); - mDaemon = null; - mCurrentUserId = UserHandle.USER_NULL; + if (mCallback != null) { + mCallback.onHardwareUnavailable(); + } } }); } @@ -262,20 +291,27 @@ class Fingerprint21 implements IHwBinder.DeathRecipient { enumerateConsumer.onEnumerationResult(fp, remaining); }); } - }; + } - Fingerprint21(@NonNull Context context, int sensorId, + Fingerprint21(@NonNull Context context, @NonNull BiometricScheduler scheduler, + @NonNull Handler handler, int sensorId, @NonNull LockoutResetDispatcher lockoutResetDispatcher, - @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { + @NonNull HalResultController controller) { mContext = context; + mScheduler = scheduler; + mHandler = handler; mActivityTaskManager = ActivityTaskManager.getService(); - mHandler = new Handler(Looper.getMainLooper()); + mTaskStackListener = new BiometricTaskStackListener(); mAuthenticatorIds = Collections.synchronizedMap(new HashMap<>()); mLazyDaemon = Fingerprint21.this::getDaemon; mLockoutResetDispatcher = lockoutResetDispatcher; mLockoutTracker = new LockoutFrameworkImpl(context, mLockoutResetCallback); - mScheduler = new BiometricScheduler(TAG, gestureAvailabilityDispatcher); + mHalResultController = controller; + mHalResultController.setCallback(() -> { + mDaemon = null; + mCurrentUserId = UserHandle.USER_NULL; + }); try { ActivityManager.getService().registerUserSwitchObserver(mUserSwitchObserver, TAG); @@ -300,7 +336,21 @@ class Fingerprint21 implements IHwBinder.DeathRecipient { final @FingerprintSensorProperties.SensorType int sensorType = isUdfps ? FingerprintSensorProperties.TYPE_UDFPS : FingerprintSensorProperties.TYPE_REAR; - mSensorProperties = new FingerprintSensorProperties(sensorId, sensorType); + // resetLockout is controlled by the framework, so hardwareAuthToken is not required + final boolean resetLockoutRequiresHardwareAuthToken = false; + mSensorProperties = new FingerprintSensorProperties(sensorId, sensorType, + resetLockoutRequiresHardwareAuthToken); + } + + static Fingerprint21 newInstance(@NonNull Context context, int sensorId, + @NonNull LockoutResetDispatcher lockoutResetDispatcher, + @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { + final Handler handler = new Handler(Looper.getMainLooper()); + final BiometricScheduler scheduler = + new BiometricScheduler(TAG, gestureAvailabilityDispatcher); + final HalResultController controller = new HalResultController(context, handler, scheduler); + return new Fingerprint21(context, scheduler, handler, sensorId, lockoutResetDispatcher, + controller); } @Override @@ -355,7 +405,7 @@ class Fingerprint21 implements IHwBinder.DeathRecipient { // successfully set. long halId = 0; try { - halId = mDaemon.setNotify(mDaemonCallback); + halId = mDaemon.setNotify(mHalResultController); } catch (RemoteException e) { Slog.e(TAG, "Failed to set callback for fingerprint HAL", e); mDaemon = null; @@ -373,6 +423,9 @@ class Fingerprint21 implements IHwBinder.DeathRecipient { return mDaemon; } + @Nullable IUdfpsOverlayController getUdfpsOverlayController() { + return mUdfpsOverlayController; + } @LockoutTracker.LockoutMode int getLockoutModeForUser(int userId) { return mLockoutTracker.getLockoutModeForUser(userId); } @@ -409,14 +462,17 @@ class Fingerprint21 implements IHwBinder.DeathRecipient { new FingerprintUpdateActiveUserClient(mContext, mLazyDaemon, targetUserId, mContext.getOpPackageName(), mSensorProperties.sensorId, mCurrentUserId, hasEnrolled, mAuthenticatorIds); - mScheduler.scheduleClientMonitor(client, (clientMonitor, success) -> { - if (success) { - mCurrentUserId = targetUserId; + mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() { + @Override + public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, boolean success) { + if (success) { + mCurrentUserId = targetUserId; + } } }); } - void scheduleResetLockout(int userId, byte[] hardwareAuthToken) { + void scheduleResetLockout(int userId) { // Fingerprint2.1 keeps track of lockout in the framework. Let's just do it on the handler // thread. mHandler.post(() -> { @@ -453,12 +509,16 @@ class Fingerprint21 implements IHwBinder.DeathRecipient { mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken, opPackageName, FingerprintUtils.getInstance(), ENROLL_TIMEOUT_SEC, mSensorProperties.sensorId, mUdfpsOverlayController); - mScheduler.scheduleClientMonitor(client, ((clientMonitor, success) -> { - if (success) { - // Update authenticatorIds - scheduleUpdateActiveUserWithoutHandler(clientMonitor.getTargetUserId()); + mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() { + @Override + public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, + boolean success) { + if (success) { + // Update authenticatorIds + scheduleUpdateActiveUserWithoutHandler(clientMonitor.getTargetUserId()); + } } - })); + }); }); } @@ -485,7 +545,7 @@ class Fingerprint21 implements IHwBinder.DeathRecipient { void scheduleAuthenticate(@NonNull IBinder token, long operationId, int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener, @NonNull String opPackageName, - @Nullable Surface surface, boolean restricted, int statsClient) { + boolean restricted, int statsClient, boolean isKeyguard) { mHandler.post(() -> { scheduleUpdateActiveUserWithoutHandler(userId); @@ -493,8 +553,8 @@ class Fingerprint21 implements IHwBinder.DeathRecipient { final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient( mContext, mLazyDaemon, token, listener, userId, operationId, restricted, opPackageName, cookie, false /* requireConfirmation */, - mSensorProperties.sensorId, isStrongBiometric, surface, statsClient, - mTaskStackListener, mLockoutTracker, mUdfpsOverlayController); + mSensorProperties.sensorId, isStrongBiometric, statsClient, + mTaskStackListener, mLockoutTracker, mUdfpsOverlayController, isKeyguard); mScheduler.scheduleClientMonitor(client); }); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21UdfpsMock.java new file mode 100644 index 000000000000..1a6ad46fce67 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21UdfpsMock.java @@ -0,0 +1,557 @@ +/* + * 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.server.biometrics.sensors.fingerprint; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.trust.TrustManager; +import android.content.ContentResolver; +import android.content.Context; +import android.hardware.fingerprint.FingerprintManager; +import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback; +import android.hardware.fingerprint.FingerprintManager.AuthenticationResult; +import android.hardware.fingerprint.FingerprintSensorProperties; +import android.hardware.fingerprint.IUdfpsOverlayController; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.RemoteException; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.Slog; +import android.util.SparseBooleanArray; + +import com.android.server.biometrics.sensors.AuthenticationConsumer; +import com.android.server.biometrics.sensors.BiometricScheduler; +import com.android.server.biometrics.sensors.ClientMonitor; +import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; +import com.android.server.biometrics.sensors.LockoutResetDispatcher; + +import java.util.ArrayList; +import java.util.Random; + +/** + * A mockable/testable provider of the {@link android.hardware.biometrics.fingerprint.V2_3} HIDL + * interface. This class is intended simulate UDFPS logic for devices that do not have an actual + * fingerprint@2.3 HAL (where UDFPS starts to become supported) + * + * UDFPS "accept" can only happen within a set amount of time after a sensor authentication. This is + * specified by {@link MockHalResultController#AUTH_VALIDITY_MS}. Touches after this duration will + * be treated as "reject". + * + * This class provides framework logic to emulate, for testing only, the UDFPS functionalies below: + * + * 1) IF either A) the caller is keyguard, and the device is not in a trusted state (authenticated + * via biometric sensor or unlocked with a trust agent {@see android.app.trust.TrustManager}, OR + * B) the caller is not keyguard, and regardless of trusted state, AND (following applies to both + * (A) and (B) above) {@link FingerprintManager#onFingerDown(int, int, float, float)} is + * received, this class will respond with {@link AuthenticationCallback#onAuthenticationFailed()} + * after a tunable flat_time + variance_time. + * + * In the case above (1), callers must not receive a successful authentication event here because + * the sensor has not actually been authenticated. + * + * 2) IF A) the caller is keyguard and the device is not in a trusted state, OR B) the caller is not + * keyguard and regardless of trusted state, AND (following applies to both (A) and (B)) the + * sensor is touched and the fingerprint is accepted by the HAL, and then + * {@link FingerprintManager#onFingerDown(int, int, float, float)} is received, this class will + * respond with {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} + * after a tunable flat_time + variance_time. Note that the authentication callback from the + * sensor is held until {@link FingerprintManager#onFingerDown(int, int, float, float)} is + * invoked. + * + * In the case above (2), callers can receive a successful authentication callback because the + * real sensor was authenticated. Note that even though the real sensor was touched, keyguard + * fingerprint authentication does not put keyguard into a trusted state because the + * authentication callback is held until onFingerDown was invoked. This allows callers such as + * keyguard to simulate a realistic path. + * + * 3) IF the caller is keyguard AND the device in a trusted state and then + * {@link FingerprintManager#onFingerDown(int, int, float, float)} is received, this class will + * respond with {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} + * after a tunable flat_time + variance time. + * + * In the case above (3), since the device is already unlockable via trust agent, it's fine to + * simulate the successful auth path. Non-keyguard clients will fall into either (1) or (2) + * above. + * + * This class currently does not simulate false rejection. Conversely, this class relies on the + * real hardware sensor so does not affect false acceptance. + */ +@SuppressWarnings("deprecation") +public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManager.TrustListener { + + private static final String TAG = "Fingerprint21UdfpsMock"; + + // Secure setting integer. If true, the system will load this class to enable udfps testing. + public static final String CONFIG_ENABLE_TEST_UDFPS = + "com.android.server.biometrics.sensors.fingerprint.test_udfps.enable"; + // Secure setting integer. A fixed duration intended to simulate something like the duration + // required for image capture. + private static final String CONFIG_AUTH_DELAY_PT1 = + "com.android.server.biometrics.sensors.fingerprint.test_udfps.auth_delay_pt1"; + // Secure setting integer. A fixed duration intended to simulate something like the duration + // required for template matching to complete. + private static final String CONFIG_AUTH_DELAY_PT2 = + "com.android.server.biometrics.sensors.fingerprint.test_udfps.auth_delay_pt2"; + // Secure setting integer. A random value between [-randomness, randomness] will be added to the + // capture delay above for each accept/reject. + private static final String CONFIG_AUTH_DELAY_RANDOMNESS = + "com.android.server.biometrics.sensors.fingerprint.test_udfps.auth_delay_randomness"; + + private static final int DEFAULT_AUTH_DELAY_PT1_MS = 300; + private static final int DEFAULT_AUTH_DELAY_PT2_MS = 400; + private static final int DEFAULT_AUTH_DELAY_RANDOMNESS_MS = 100; + + @NonNull private final TestableBiometricScheduler mScheduler; + @NonNull private final Handler mHandler; + @NonNull private final FingerprintSensorProperties mSensorProperties; + @NonNull private final MockHalResultController mMockHalResultController; + @NonNull private final TrustManager mTrustManager; + @NonNull private final SparseBooleanArray mUserHasTrust; + @NonNull private final Random mRandom; + @NonNull private final FakeRejectRunnable mFakeRejectRunnable; + @NonNull private final FakeAcceptRunnable mFakeAcceptRunnable; + @NonNull private final RestartAuthRunnable mRestartAuthRunnable; + + private static class TestableBiometricScheduler extends BiometricScheduler { + @NonNull private final TestableInternalCallback mInternalCallback; + @NonNull private Fingerprint21UdfpsMock mFingerprint21; + + TestableBiometricScheduler(@NonNull String tag, + @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { + super(tag, gestureAvailabilityDispatcher); + mInternalCallback = new TestableInternalCallback(); + } + + class TestableInternalCallback extends InternalCallback { + @Override + public void onClientStarted(ClientMonitor<?> clientMonitor) { + super.onClientStarted(clientMonitor); + Slog.d(TAG, "Client started: " + clientMonitor); + mFingerprint21.setDebugMessage("Started: " + clientMonitor); + } + + @Override + public void onClientFinished(ClientMonitor<?> clientMonitor, boolean success) { + super.onClientFinished(clientMonitor, success); + Slog.d(TAG, "Client finished: " + clientMonitor); + mFingerprint21.setDebugMessage("Finished: " + clientMonitor); + } + } + + void init(@NonNull Fingerprint21UdfpsMock fingerprint21) { + mFingerprint21 = fingerprint21; + } + + /** + * Expose the internal finish callback so it can be used for testing + */ + @Override + @NonNull protected InternalCallback getInternalCallback() { + return mInternalCallback; + } + } + + /** + * All of the mocking/testing should happen in here. This way we don't need to modify the + * {@link com.android.server.biometrics.sensors.ClientMonitor} implementations and can run the + * real path there. + */ + private static class MockHalResultController extends HalResultController { + + // Duration for which a sensor authentication can be treated as UDFPS success. + private static final int AUTH_VALIDITY_MS = 10 * 1000; // 10 seconds + + static class LastAuthArgs { + @NonNull final AuthenticationConsumer lastAuthenticatedClient; + final long deviceId; + final int fingerId; + final int groupId; + @Nullable final ArrayList<Byte> token; + + LastAuthArgs(@NonNull AuthenticationConsumer authenticationConsumer, long deviceId, + int fingerId, int groupId, @Nullable ArrayList<Byte> token) { + lastAuthenticatedClient = authenticationConsumer; + this.deviceId = deviceId; + this.fingerId = fingerId; + this.groupId = groupId; + if (token == null) { + this.token = null; + } else { + // Store a copy so the owner can be GC'd + this.token = new ArrayList<>(token); + } + } + } + + // Initialized after the constructor, but before it's ever used. + @NonNull private RestartAuthRunnable mRestartAuthRunnable; + @NonNull private Fingerprint21UdfpsMock mFingerprint21; + @Nullable private LastAuthArgs mLastAuthArgs; + + MockHalResultController(@NonNull Context context, @NonNull Handler handler, + @NonNull BiometricScheduler scheduler) { + super(context, handler, scheduler); + } + + void init(@NonNull RestartAuthRunnable restartAuthRunnable, + @NonNull Fingerprint21UdfpsMock fingerprint21) { + mRestartAuthRunnable = restartAuthRunnable; + mFingerprint21 = fingerprint21; + } + + @Nullable AuthenticationConsumer getLastAuthenticatedClient() { + return mLastAuthArgs != null ? mLastAuthArgs.lastAuthenticatedClient : null; + } + + /** + * Intercepts the HAL authentication and holds it until the UDFPS simulation decides + * that authentication finished. + */ + @Override + public void onAuthenticated(long deviceId, int fingerId, int groupId, + ArrayList<Byte> token) { + mHandler.post(() -> { + final ClientMonitor<?> client = mScheduler.getCurrentClient(); + if (!(client instanceof AuthenticationConsumer)) { + Slog.e(TAG, "Non authentication consumer: " + client); + return; + } + + final boolean accepted = fingerId != 0; + if (accepted) { + mFingerprint21.setDebugMessage("Finger accepted"); + } else { + mFingerprint21.setDebugMessage("Finger rejected"); + } + + final AuthenticationConsumer authenticationConsumer = + (AuthenticationConsumer) client; + mLastAuthArgs = new LastAuthArgs(authenticationConsumer, deviceId, fingerId, + groupId, token); + + // Remove any existing restart runnbables since auth just started, and put a new + // one on the queue. + mHandler.removeCallbacks(mRestartAuthRunnable); + mRestartAuthRunnable.setLastAuthReference(authenticationConsumer); + mHandler.postDelayed(mRestartAuthRunnable, AUTH_VALIDITY_MS); + }); + } + + /** + * Calls through to the real interface and notifies clients of accept/reject. + */ + void sendAuthenticated(long deviceId, int fingerId, int groupId, + ArrayList<Byte> token) { + Slog.d(TAG, "sendAuthenticated: " + (fingerId != 0)); + mFingerprint21.setDebugMessage("Udfps match: " + (fingerId != 0)); + super.onAuthenticated(deviceId, fingerId, groupId, token); + } + } + + static Fingerprint21UdfpsMock newInstance(@NonNull Context context, int sensorId, + @NonNull LockoutResetDispatcher lockoutResetDispatcher, + @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { + Slog.d(TAG, "Creating Fingerprint23Mock!"); + + final Handler handler = new Handler(Looper.getMainLooper()); + final TestableBiometricScheduler scheduler = + new TestableBiometricScheduler(TAG, gestureAvailabilityDispatcher); + final MockHalResultController controller = + new MockHalResultController(context, handler, scheduler); + return new Fingerprint21UdfpsMock(context, scheduler, handler, sensorId, + lockoutResetDispatcher, controller); + } + + private static abstract class FakeFingerRunnable implements Runnable { + private long mFingerDownTime; + private int mCaptureDuration; + + /** + * @param fingerDownTime System time when onFingerDown occurred + * @param captureDuration Duration that the finger needs to be down for + */ + void setSimulationTime(long fingerDownTime, int captureDuration) { + mFingerDownTime = fingerDownTime; + mCaptureDuration = captureDuration; + } + + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + boolean isImageCaptureComplete() { + return System.currentTimeMillis() - mFingerDownTime > mCaptureDuration; + } + } + + private final class FakeRejectRunnable extends FakeFingerRunnable { + @Override + public void run() { + mMockHalResultController.sendAuthenticated(0, 0, 0, null); + } + } + + private final class FakeAcceptRunnable extends FakeFingerRunnable { + @Override + public void run() { + if (mMockHalResultController.mLastAuthArgs == null) { + // This can happen if the user has trust agents enabled, which make lockscreen + // dismissable. Send a fake non-zero (accept) finger. + Slog.d(TAG, "Sending fake finger"); + mMockHalResultController.sendAuthenticated(1 /* deviceId */, + 1 /* fingerId */, 1 /* groupId */, null /* token */); + } else { + mMockHalResultController.sendAuthenticated( + mMockHalResultController.mLastAuthArgs.deviceId, + mMockHalResultController.mLastAuthArgs.fingerId, + mMockHalResultController.mLastAuthArgs.groupId, + mMockHalResultController.mLastAuthArgs.token); + } + } + } + + /** + * The fingerprint HAL allows multiple (5) fingerprint attempts per HIDL invocation of the + * authenticate method. However, valid fingerprint authentications are invalidated after + * {@link MockHalResultController#AUTH_VALIDITY_MS}, meaning UDFPS touches will be reported as + * rejects if touched after that duration. However, since a valid fingerprint was detected, the + * HAL and FingerprintService will not look for subsequent fingerprints. + * + * In order to keep the FingerprintManager API consistent (that multiple fingerprint attempts + * are allowed per auth lifecycle), we internally cancel and restart authentication so that the + * sensor is responsive again. + */ + private static final class RestartAuthRunnable implements Runnable { + @NonNull private final Fingerprint21UdfpsMock mFingerprint21; + @NonNull private final TestableBiometricScheduler mScheduler; + + // Store a reference to the auth consumer that should be invalidated. + private AuthenticationConsumer mLastAuthConsumer; + + RestartAuthRunnable(@NonNull Fingerprint21UdfpsMock fingerprint21, + @NonNull TestableBiometricScheduler scheduler) { + mFingerprint21 = fingerprint21; + mScheduler = scheduler; + } + + void setLastAuthReference(AuthenticationConsumer lastAuthConsumer) { + mLastAuthConsumer = lastAuthConsumer; + } + + @Override + public void run() { + final ClientMonitor<?> client = mScheduler.getCurrentClient(); + + // We don't care about FingerprintDetectClient, since accept/rejects are both OK. UDFPS + // rejects will just simulate the path where non-enrolled fingers are presented. + if (!(client instanceof FingerprintAuthenticationClient)) { + Slog.e(TAG, "Non-FingerprintAuthenticationClient client: " + client); + return; + } + + // Perhaps the runnable is stale, or the user stopped/started auth manually. Do not + // restart auth in this case. + if (client != mLastAuthConsumer) { + Slog.e(TAG, "Current client: " + client + + " does not match mLastAuthConsumer: " + mLastAuthConsumer); + return; + } + + Slog.d(TAG, "Restarting auth, current: " + client); + mFingerprint21.setDebugMessage("Auth timed out"); + + final FingerprintAuthenticationClient authClient = + (FingerprintAuthenticationClient) client; + // Store the authClient parameters so it can be rescheduled + final IBinder token = client.getToken(); + final long operationId = authClient.getOperationId(); + final int user = client.getTargetUserId(); + final int cookie = client.getCookie(); + final ClientMonitorCallbackConverter listener = client.getListener(); + final String opPackageName = client.getOwnerString(); + final boolean restricted = authClient.isRestricted(); + final int statsClient = client.getStatsClient(); + final boolean isKeyguard = authClient.isKeyguard(); + + // Don't actually send cancel() to the HAL, since successful auth already finishes + // HAL authenticate() lifecycle. Just + mScheduler.getInternalCallback().onClientFinished(client, true /* success */); + + // Schedule this only after we invoke onClientFinished for the previous client, so that + // internal preemption logic is not run. + mFingerprint21.scheduleAuthenticate(token, operationId, user, cookie, + listener, opPackageName, restricted, statsClient, isKeyguard); + } + } + + private Fingerprint21UdfpsMock(@NonNull Context context, + @NonNull TestableBiometricScheduler scheduler, + @NonNull Handler handler, int sensorId, + @NonNull LockoutResetDispatcher lockoutResetDispatcher, + @NonNull MockHalResultController controller) { + super(context, scheduler, handler, sensorId, lockoutResetDispatcher, controller); + mScheduler = scheduler; + mScheduler.init(this); + mHandler = handler; + // resetLockout is controlled by the framework, so hardwareAuthToken is not required + final boolean resetLockoutRequiresHardwareAuthToken = false; + mSensorProperties = new FingerprintSensorProperties(sensorId, + FingerprintSensorProperties.TYPE_UDFPS, resetLockoutRequiresHardwareAuthToken); + mMockHalResultController = controller; + mUserHasTrust = new SparseBooleanArray(); + mTrustManager = context.getSystemService(TrustManager.class); + mTrustManager.registerTrustListener(this); + mRandom = new Random(); + mFakeRejectRunnable = new FakeRejectRunnable(); + mFakeAcceptRunnable = new FakeAcceptRunnable(); + mRestartAuthRunnable = new RestartAuthRunnable(this, mScheduler); + + // We can't initialize this during MockHalresultController's constructor due to a circular + // dependency. + mMockHalResultController.init(mRestartAuthRunnable, this); + } + + @Override + public void onTrustChanged(boolean enabled, int userId, int flags) { + mUserHasTrust.put(userId, enabled); + } + + @Override + public void onTrustManagedChanged(boolean enabled, int userId) { + + } + + @Override + public void onTrustError(CharSequence message) { + + } + + @Override + @NonNull + FingerprintSensorProperties getFingerprintSensorProperties() { + return mSensorProperties; + } + + @Override + void onFingerDown(int x, int y, float minor, float major) { + mHandler.post(() -> { + Slog.d(TAG, "onFingerDown"); + final AuthenticationConsumer lastAuthenticatedConsumer = + mMockHalResultController.getLastAuthenticatedClient(); + final ClientMonitor<?> currentScheduledClient = mScheduler.getCurrentClient(); + + if (currentScheduledClient == null) { + Slog.d(TAG, "Not authenticating"); + return; + } + + mHandler.removeCallbacks(mFakeRejectRunnable); + mHandler.removeCallbacks(mFakeAcceptRunnable); + + // The sensor was authenticated, is still the currently scheduled client, and the + // user touched the UDFPS affordance. Pretend that auth succeeded. + final boolean authenticatedClientIsCurrent = lastAuthenticatedConsumer != null + && lastAuthenticatedConsumer == currentScheduledClient; + // User is unlocked on keyguard via Trust Agent + final boolean keyguardAndTrusted; + if (currentScheduledClient instanceof FingerprintAuthenticationClient) { + keyguardAndTrusted = ((FingerprintAuthenticationClient) currentScheduledClient) + .isKeyguard() + && mUserHasTrust.get(currentScheduledClient.getTargetUserId(), false); + } else { + keyguardAndTrusted = false; + } + + final int captureDuration = getNewCaptureDuration(); + final int matchingDuration = getMatchingDuration(); + final int totalDuration = captureDuration + matchingDuration; + setDebugMessage("Duration: " + totalDuration + + " (" + captureDuration + " + " + matchingDuration + ")"); + if (authenticatedClientIsCurrent || keyguardAndTrusted) { + mFakeAcceptRunnable.setSimulationTime(System.currentTimeMillis(), captureDuration); + mHandler.postDelayed(mFakeAcceptRunnable, totalDuration); + } else if (currentScheduledClient instanceof AuthenticationConsumer) { + // Something is authenticating but authentication has not succeeded yet. Pretend + // that auth rejected. + mFakeRejectRunnable.setSimulationTime(System.currentTimeMillis(), captureDuration); + mHandler.postDelayed(mFakeRejectRunnable, totalDuration); + } + }); + } + + @Override + void onFingerUp() { + mHandler.post(() -> { + Slog.d(TAG, "onFingerUp"); + + // Only one of these can be on the handler at any given time (see onFingerDown). If + // image capture is not complete, send ACQUIRED_TOO_FAST and remove the runnable from + // the handler. Image capture (onFingerDown) needs to happen again. + if (mHandler.hasCallbacks(mFakeRejectRunnable) + && !mFakeRejectRunnable.isImageCaptureComplete()) { + mHandler.removeCallbacks(mFakeRejectRunnable); + mMockHalResultController.onAcquired(0 /* deviceId */, + FingerprintManager.FINGERPRINT_ACQUIRED_TOO_FAST, + 0 /* vendorCode */); + } else if (mHandler.hasCallbacks(mFakeAcceptRunnable) + && !mFakeAcceptRunnable.isImageCaptureComplete()) { + mHandler.removeCallbacks(mFakeAcceptRunnable); + mMockHalResultController.onAcquired(0 /* deviceId */, + FingerprintManager.FINGERPRINT_ACQUIRED_TOO_FAST, + 0 /* vendorCode */); + } + }); + } + + private int getNewCaptureDuration() { + final ContentResolver contentResolver = mContext.getContentResolver(); + final int captureTime = Settings.Secure.getIntForUser(contentResolver, + CONFIG_AUTH_DELAY_PT1, + DEFAULT_AUTH_DELAY_PT1_MS, + UserHandle.USER_CURRENT); + final int randomDelayRange = Settings.Secure.getIntForUser(contentResolver, + CONFIG_AUTH_DELAY_RANDOMNESS, + DEFAULT_AUTH_DELAY_RANDOMNESS_MS, + UserHandle.USER_CURRENT); + final int randomDelay = mRandom.nextInt(randomDelayRange * 2) - randomDelayRange; + + // Must be at least 0 + return Math.max(captureTime + randomDelay, 0); + } + + private int getMatchingDuration() { + final int matchingTime = Settings.Secure.getIntForUser(mContext.getContentResolver(), + CONFIG_AUTH_DELAY_PT2, + DEFAULT_AUTH_DELAY_PT2_MS, + UserHandle.USER_CURRENT); + + // Must be at least 0 + return Math.max(matchingTime, 0); + } + + private void setDebugMessage(String message) { + try { + final IUdfpsOverlayController controller = getUdfpsOverlayController(); + // Things can happen before SysUI loads and sets the controller. + if (controller != null) { + Slog.d(TAG, "setDebugMessage: " + message); + controller.setDebugMessage(message); + } + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception when sending message: " + message, e); + } + } +} diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticationClient.java index 1564056cfdbd..99d348a780f3 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticationClient.java @@ -29,7 +29,6 @@ import android.hardware.fingerprint.IUdfpsOverlayController; import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; -import android.view.Surface; import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; @@ -47,6 +46,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi private static final String TAG = "Biometrics/FingerprintAuthClient"; + private final boolean mIsKeyguard; private final LockoutFrameworkImpl mLockoutFrameworkImpl; @Nullable private final IUdfpsOverlayController mUdfpsOverlayController; @@ -54,16 +54,17 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi @NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId, boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation, - int sensorId, boolean isStrongBiometric, @Nullable Surface surface, int statsClient, + int sensorId, boolean isStrongBiometric, int statsClient, @NonNull TaskStackListener taskStackListener, @NonNull LockoutFrameworkImpl lockoutTracker, - @Nullable IUdfpsOverlayController udfpsOverlayController) { + @Nullable IUdfpsOverlayController udfpsOverlayController, boolean isKeyguard) { super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner, cookie, requireConfirmation, sensorId, isStrongBiometric, BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener, lockoutTracker); mLockoutFrameworkImpl = lockoutTracker; mUdfpsOverlayController = udfpsOverlayController; + mIsKeyguard = isKeyguard; } @Override @@ -79,7 +80,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi if (authenticated) { resetFailedAttempts(getTargetUserId()); UdfpsHelper.hideUdfpsOverlay(mUdfpsOverlayController); - mFinishCallback.onClientFinished(this, true /* success */); + mCallback.onClientFinished(this, true /* success */); } else { final @LockoutTracker.LockoutMode int lockoutMode = mLockoutFrameworkImpl.getLockoutModeForUser(getTargetUserId()); @@ -119,7 +120,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); UdfpsHelper.hideUdfpsOverlay(mUdfpsOverlayController); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } @@ -132,7 +133,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi Slog.e(TAG, "Remote exception when requesting cancel", e); onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } @@ -145,4 +146,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi public void onFingerUp() { UdfpsHelper.onFingerUp(getFreshDaemon()); } + + public boolean isKeyguard() { + return mIsKeyguard; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java index 3418c466aa69..21a46d58a3b3 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java @@ -75,11 +75,6 @@ public final class FingerprintAuthenticator extends IBiometricAuthenticator.Stub } @Override - public void resetLockout(int userId, byte[] hardwareAuthToken) throws RemoteException { - mFingerprintService.resetLockout(userId, hardwareAuthToken); - } - - @Override public long getAuthenticatorId(int callingUserId) throws RemoteException { return mFingerprintService.getAuthenticatorId(callingUserId); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintDetectClient.java index 8b295f8f4931..8652ee403089 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintDetectClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintDetectClient.java @@ -68,13 +68,13 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint> Slog.e(TAG, "Remote exception when requesting cancel", e); onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } @Override - public void start(@NonNull FinishCallback finishCallback) { - super.start(finishCallback); + public void start(@NonNull Callback callback) { + super.start(callback); startHalOperation(); } @@ -88,7 +88,7 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint> onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); UdfpsHelper.hideUdfpsOverlay(mUdfpsOverlayController); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintEnrollClient.java index 32f8b8fe8b26..d5db6e411b95 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintEnrollClient.java @@ -79,7 +79,7 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); UdfpsHelper.hideUdfpsOverlay(mUdfpsOverlayController); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } @@ -92,7 +92,7 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint Slog.e(TAG, "Remote exception when requesting cancel", e); onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintInternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintInternalEnumerateClient.java index 240c3c56f75e..834bf42eba3f 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintInternalEnumerateClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintInternalEnumerateClient.java @@ -52,7 +52,7 @@ class FingerprintInternalEnumerateClient extends InternalEnumerateClient<IBiomet getFreshDaemon().enumerate(); } catch (RemoteException e) { Slog.e(TAG, "Remote exception when requesting enumerate", e); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintRemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintRemovalClient.java index a9336ef6a6c2..9f5456300884 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintRemovalClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintRemovalClient.java @@ -54,7 +54,7 @@ class FingerprintRemovalClient extends RemovalClient<IBiometricsFingerprint> { getFreshDaemon().remove(getTargetUserId(), mBiometricId); } catch (RemoteException e) { Slog.e(TAG, "Remote exception when requesting remove", e); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java index e4387c9e2b81..7c7da118df10 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java @@ -25,6 +25,7 @@ import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import static android.Manifest.permission.USE_FINGERPRINT; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; @@ -38,14 +39,17 @@ import android.hardware.fingerprint.IFingerprintService; import android.hardware.fingerprint.IFingerprintServiceReceiver; import android.hardware.fingerprint.IUdfpsOverlayController; import android.os.Binder; +import android.os.Build; import android.os.IBinder; import android.os.NativeHandle; import android.os.Process; import android.os.UserHandle; +import android.provider.Settings; import android.util.EventLog; import android.util.Slog; import android.view.Surface; +import com.android.internal.R; import com.android.internal.util.DumpUtils; import com.android.internal.widget.LockPatternUtils; import com.android.server.SystemService; @@ -94,10 +98,16 @@ public class FingerprintService extends SystemService { } @Override // Binder call - public void generateChallenge(IBinder token, IFingerprintServiceReceiver receiver, - String opPackageName) { + public void generateChallenge(IBinder token, int sensorId, + IFingerprintServiceReceiver receiver, String opPackageName) { Utils.checkPermission(getContext(), MANAGE_FINGERPRINT); - mFingerprint21.scheduleGenerateChallenge(token, receiver, opPackageName); + + if (sensorId == mFingerprint21.getFingerprintSensorProperties().sensorId) { + mFingerprint21.scheduleGenerateChallenge(token, receiver, opPackageName); + return; + } + + Slog.w(TAG, "No matching sensor for generateChallenge, sensorId: " + sensorId); } @Override // Binder call @@ -158,8 +168,8 @@ public class FingerprintService extends SystemService { final int statsClient = isKeyguard ? BiometricsProtoEnums.CLIENT_KEYGUARD : BiometricsProtoEnums.CLIENT_FINGERPRINT_MANAGER; mFingerprint21.scheduleAuthenticate(token, operationId, userId, 0 /* cookie */, - new ClientMonitorCallbackConverter(receiver), opPackageName, surface, - restricted, statsClient); + new ClientMonitorCallbackConverter(receiver), opPackageName, + restricted, statsClient, isKeyguard); } @Override @@ -193,8 +203,8 @@ public class FingerprintService extends SystemService { final boolean restricted = true; // BiometricPrompt is always restricted mFingerprint21.scheduleAuthenticate(token, operationId, userId, cookie, - new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, surface, - restricted, BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT); + new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, restricted, + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, false /* isKeyguard */); } @Override // Binder call @@ -343,9 +353,16 @@ public class FingerprintService extends SystemService { } @Override // Binder call - public void resetLockout(int userId, byte [] hardwareAuthToken) { + public void resetLockout(IBinder token, int sensorId, int userId, + @Nullable byte [] hardwareAuthToken, String opPackageName) { Utils.checkPermission(getContext(), RESET_FINGERPRINT_LOCKOUT); - mFingerprint21.scheduleResetLockout(userId, hardwareAuthToken); + + if (sensorId == mFingerprint21.getFingerprintSensorProperties().sensorId) { + mFingerprint21.scheduleResetLockout(userId); + return; + } + + Slog.w(TAG, "No matching sensor for resetLockout, sensorId: " + sensorId); } @Override @@ -369,8 +386,18 @@ public class FingerprintService extends SystemService { @Override // Binder call public void initializeConfiguration(int sensorId) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); - mFingerprint21 = new Fingerprint21(getContext(), sensorId, mLockoutResetDispatcher, - mGestureAvailabilityDispatcher); + + if ((Build.IS_USERDEBUG || Build.IS_ENG) + && getContext().getResources().getBoolean(R.bool.allow_test_udfps) + && Settings.Secure.getIntForUser(getContext().getContentResolver(), + Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */, + UserHandle.USER_CURRENT) != 0) { + mFingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(), sensorId, + mLockoutResetDispatcher, mGestureAvailabilityDispatcher); + } else { + mFingerprint21 = Fingerprint21.newInstance(getContext(), sensorId, + mLockoutResetDispatcher, mGestureAvailabilityDispatcher); + } } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUpdateActiveUserClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUpdateActiveUserClient.java index e1082ae51575..c1c3593db564 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUpdateActiveUserClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUpdateActiveUserClient.java @@ -22,7 +22,6 @@ import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint; import android.os.Build; import android.os.Environment; -import android.os.IBinder; import android.os.RemoteException; import android.os.SELinux; import android.util.Slog; @@ -58,8 +57,8 @@ public class FingerprintUpdateActiveUserClient extends ClientMonitor<IBiometrics } @Override - public void start(@NonNull FinishCallback finishCallback) { - super.start(finishCallback); + public void start(@NonNull Callback callback) { + super.start(callback); if (mCurrentUserId == getTargetUserId()) { Slog.d(TAG, "Already user: " + mCurrentUserId + ", refreshing authenticatorId"); @@ -69,7 +68,7 @@ public class FingerprintUpdateActiveUserClient extends ClientMonitor<IBiometrics } catch (RemoteException e) { Slog.e(TAG, "Unable to refresh authenticatorId", e); } - finishCallback.onClientFinished(this, true /* success */); + callback.onClientFinished(this, true /* success */); return; } @@ -89,7 +88,7 @@ public class FingerprintUpdateActiveUserClient extends ClientMonitor<IBiometrics if (!mDirectory.exists()) { if (!mDirectory.mkdir()) { Slog.e(TAG, "Cannot make directory: " + mDirectory.getAbsolutePath()); - finishCallback.onClientFinished(this, false /* success */); + callback.onClientFinished(this, false /* success */); return; } // Calling mkdir() from this process will create a directory with our @@ -97,7 +96,7 @@ public class FingerprintUpdateActiveUserClient extends ClientMonitor<IBiometrics // the label. if (!SELinux.restorecon(mDirectory)) { Slog.e(TAG, "Restorecons failed. Directory will have wrong label."); - finishCallback.onClientFinished(this, false /* success */); + callback.onClientFinished(this, false /* success */); return; } } @@ -116,10 +115,10 @@ public class FingerprintUpdateActiveUserClient extends ClientMonitor<IBiometrics getFreshDaemon().setActiveGroup(getTargetUserId(), mDirectory.getAbsolutePath()); mAuthenticatorIds.put(getTargetUserId(), mHasEnrolledBiometrics ? getFreshDaemon().getAuthenticatorId() : 0L); - mFinishCallback.onClientFinished(this, true /* success */); + mCallback.onClientFinished(this, true /* success */); } catch (RemoteException e) { Slog.e(TAG, "Failed to setActiveGroup: " + e); - mFinishCallback.onClientFinished(this, false /* success */); + mCallback.onClientFinished(this, false /* success */); } } } diff --git a/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java index 9e0405792746..0400ef522142 100644 --- a/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java +++ b/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java @@ -70,10 +70,6 @@ public final class IrisAuthenticator extends IBiometricAuthenticator.Stub { } @Override - public void resetLockout(int userId, byte[] hardwareAuthToken) throws RemoteException { - } - - @Override public long getAuthenticatorId(int callingUserId) throws RemoteException { return 0; } diff --git a/services/core/java/com/android/server/gpu/GpuService.java b/services/core/java/com/android/server/gpu/GpuService.java index c0617ca95f9f..54794fecbf5b 100644 --- a/services/core/java/com/android/server/gpu/GpuService.java +++ b/services/core/java/com/android/server/gpu/GpuService.java @@ -65,7 +65,7 @@ public class GpuService extends SystemService { private static final String PROD_DRIVER_PROPERTY = "ro.gfx.driver.0"; private static final String DEV_DRIVER_PROPERTY = "ro.gfx.driver.1"; - private static final String GAME_DRIVER_ALLOWLIST_FILENAME = "allowlist.txt"; + private static final String UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST_FILENAME = "allowlist.txt"; private static final int BASE64_FLAGS = Base64.NO_PADDING | Base64.NO_WRAP; private final Context mContext; @@ -77,7 +77,7 @@ public class GpuService extends SystemService { private final boolean mHasProdDriver; private final boolean mHasDevDriver; private ContentResolver mContentResolver; - private long mGameDriverVersionCode; + private long mProdDriverVersionCode; private SettingsObserver mSettingsObserver; private DeviceConfigListener mDeviceConfigListener; @GuardedBy("mLock") @@ -88,7 +88,7 @@ public class GpuService extends SystemService { mContext = context; mProdDriverPackageName = SystemProperties.get(PROD_DRIVER_PROPERTY); - mGameDriverVersionCode = -1; + mProdDriverVersionCode = -1; mDevDriverPackageName = SystemProperties.get(DEV_DRIVER_PROPERTY); mPackageManager = context.getPackageManager(); mHasProdDriver = !TextUtils.isEmpty(mProdDriverPackageName); @@ -117,20 +117,20 @@ public class GpuService extends SystemService { } mSettingsObserver = new SettingsObserver(); mDeviceConfigListener = new DeviceConfigListener(); - fetchGameDriverPackageProperties(); + fetchProductionDriverPackageProperties(); processDenylists(); setDenylist(); - fetchDeveloperDriverPackageProperties(); + fetchPrereleaseDriverPackageProperties(); } } private final class SettingsObserver extends ContentObserver { - private final Uri mGameDriverDenylistsUri = - Settings.Global.getUriFor(Settings.Global.GAME_DRIVER_DENYLISTS); + private final Uri mProdDriverDenylistsUri = + Settings.Global.getUriFor(Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS); SettingsObserver() { super(new Handler()); - mContentResolver.registerContentObserver(mGameDriverDenylistsUri, false, this, + mContentResolver.registerContentObserver(mProdDriverDenylistsUri, false, this, UserHandle.USER_ALL); } @@ -140,7 +140,7 @@ public class GpuService extends SystemService { return; } - if (mGameDriverDenylistsUri.equals(uri)) { + if (mProdDriverDenylistsUri.equals(uri)) { processDenylists(); setDenylist(); } @@ -157,9 +157,11 @@ public class GpuService extends SystemService { @Override public void onPropertiesChanged(Properties properties) { synchronized (mDeviceConfigLock) { - if (properties.getKeyset().contains(Settings.Global.GAME_DRIVER_DENYLISTS)) { + if (properties.getKeyset().contains( + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS)) { parseDenylists( - properties.getString(Settings.Global.GAME_DRIVER_DENYLISTS, "")); + properties.getString( + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS, "")); setDenylist(); } } @@ -186,10 +188,10 @@ public class GpuService extends SystemService { case ACTION_PACKAGE_CHANGED: case ACTION_PACKAGE_REMOVED: if (isProdDriver) { - fetchGameDriverPackageProperties(); + fetchProductionDriverPackageProperties(); setDenylist(); } else if (isDevDriver) { - fetchDeveloperDriverPackageProperties(); + fetchPrereleaseDriverPackageProperties(); } break; default: @@ -218,7 +220,7 @@ public class GpuService extends SystemService { } } - private void fetchGameDriverPackageProperties() { + private void fetchProductionDriverPackageProperties() { final ApplicationInfo driverInfo; try { driverInfo = mPackageManager.getApplicationInfo(mProdDriverPackageName, @@ -241,15 +243,16 @@ public class GpuService extends SystemService { // Reset the allowlist. Settings.Global.putString(mContentResolver, - Settings.Global.GAME_DRIVER_ALLOWLIST, ""); - mGameDriverVersionCode = driverInfo.longVersionCode; + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST, ""); + mProdDriverVersionCode = driverInfo.longVersionCode; try { final Context driverContext = mContext.createPackageContext(mProdDriverPackageName, Context.CONTEXT_RESTRICTED); - assetToSettingsGlobal(mContext, driverContext, GAME_DRIVER_ALLOWLIST_FILENAME, - Settings.Global.GAME_DRIVER_ALLOWLIST, ","); + assetToSettingsGlobal(mContext, driverContext, + UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST_FILENAME, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST, ","); } catch (PackageManager.NameNotFoundException e) { if (DEBUG) { Slog.w(TAG, "driver package '" + mProdDriverPackageName + "' not installed"); @@ -259,11 +262,11 @@ public class GpuService extends SystemService { private void processDenylists() { String base64String = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_GAME_DRIVER, - Settings.Global.GAME_DRIVER_DENYLISTS); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS); if (base64String == null) { base64String = Settings.Global.getString(mContentResolver, - Settings.Global.GAME_DRIVER_DENYLISTS); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLISTS); } parseDenylists(base64String != null ? base64String : ""); } @@ -288,16 +291,16 @@ public class GpuService extends SystemService { private void setDenylist() { Settings.Global.putString(mContentResolver, - Settings.Global.GAME_DRIVER_DENYLIST, ""); + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLIST, ""); synchronized (mLock) { if (mDenylists == null) { return; } List<Denylist> denylists = mDenylists.getDenylistsList(); for (Denylist denylist : denylists) { - if (denylist.getVersionCode() == mGameDriverVersionCode) { + if (denylist.getVersionCode() == mProdDriverVersionCode) { Settings.Global.putString(mContentResolver, - Settings.Global.GAME_DRIVER_DENYLIST, + Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLIST, String.join(",", denylist.getPackageNamesList())); return; } @@ -305,7 +308,7 @@ public class GpuService extends SystemService { } } - private void fetchDeveloperDriverPackageProperties() { + private void fetchPrereleaseDriverPackageProperties() { final ApplicationInfo driverInfo; try { driverInfo = mPackageManager.getApplicationInfo(mDevDriverPackageName, diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 85a4515d46a0..9ab410d258cc 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -3450,9 +3450,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return InputBindResult.USER_SWITCHING; } - // Master feature flag that overrides other conditions and forces IME preRendering. + // Main feature flag that overrides other conditions and forces IME preRendering. if (DEBUG) { - Slog.v(TAG, "IME PreRendering MASTER flag: " + Slog.v(TAG, "IME PreRendering main flag: " + DebugFlags.FLAG_PRE_RENDER_IME_VIEWS.value() + ", LowRam: " + mIsLowRam); } // pre-rendering not supported on low-ram devices. diff --git a/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java b/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java new file mode 100644 index 000000000000..e3074dba26ef --- /dev/null +++ b/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java @@ -0,0 +1,253 @@ +/* + * 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.server.locksettings; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.hardware.face.FaceManager; +import android.hardware.face.FaceSensorProperties; +import android.hardware.fingerprint.FingerprintManager; +import android.hardware.fingerprint.FingerprintSensorProperties; +import android.os.Handler; +import android.os.IBinder; +import android.os.ServiceManager; +import android.service.gatekeeper.IGateKeeperService; +import android.util.ArraySet; +import android.util.Slog; + +import com.android.internal.widget.VerifyCredentialResponse; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Class that handles biometric-related work in the {@link LockSettingsService} area, for example + * resetLockout. + */ +@SuppressWarnings("deprecation") +public class BiometricDeferredQueue { + private static final String TAG = "BiometricDeferredQueue"; + + @NonNull private final Context mContext; + @NonNull private final SyntheticPasswordManager mSpManager; + @NonNull private final Handler mHandler; + @Nullable private FingerprintManager mFingerprintManager; + @Nullable private FaceManager mFaceManager; + + // Entries added by LockSettingsService once a user's synthetic password is known. At this point + // things are still keyed by userId. + @NonNull private final ArrayList<UserAuthInfo> mPendingResetLockouts; + + /** + * Authentication info for a successful user unlock via Synthetic Password. This can be used to + * perform multiple operations (e.g. resetLockout for multiple HALs/Sensors) by sending the + * Gatekeeper Password to Gatekeer multiple times, each with a sensor-specific challenge. + */ + private static class UserAuthInfo { + final int userId; + @NonNull final byte[] gatekeeperPassword; + + UserAuthInfo(int userId, @NonNull byte[] gatekeeperPassword) { + this.userId = userId; + this.gatekeeperPassword = gatekeeperPassword; + } + } + + /** + * Per-authentication callback. + */ + private static class FaceResetLockoutTask implements FaceManager.GenerateChallengeCallback { + interface FinishCallback { + void onFinished(); + } + + @NonNull FinishCallback finishCallback; + @NonNull FaceManager faceManager; + @NonNull SyntheticPasswordManager spManager; + @NonNull Set<Integer> sensorIds; // IDs of sensors waiting for challenge + @NonNull List<UserAuthInfo> pendingResetLockuts; + + FaceResetLockoutTask( + @NonNull FinishCallback finishCallback, + @NonNull FaceManager faceManager, + @NonNull SyntheticPasswordManager spManager, + @NonNull Set<Integer> sensorIds, + @NonNull List<UserAuthInfo> pendingResetLockouts) { + this.finishCallback = finishCallback; + this.faceManager = faceManager; + this.spManager = spManager; + this.sensorIds = sensorIds; + this.pendingResetLockuts = pendingResetLockouts; + } + + @Override + public void onChallengeInterrupted(int sensorId) { + Slog.w(TAG, "Challenge interrupted, sensor: " + sensorId); + // Consider re-attempting generateChallenge/resetLockout/revokeChallenge + // when onChallengeInterruptFinished is invoked + } + + @Override + public void onChallengeInterruptFinished(int sensorId) { + Slog.w(TAG, "Challenge interrupt finished, sensor: " + sensorId); + } + + @Override + public void onGenerateChallengeResult(int sensorId, long challenge) { + if (!sensorIds.contains(sensorId)) { + Slog.e(TAG, "Unknown sensorId received: " + sensorId); + return; + } + + // Challenge received for a sensor. For each sensor, reset lockout for all users. + for (UserAuthInfo userAuthInfo : pendingResetLockuts) { + Slog.d(TAG, "Resetting face lockout for sensor: " + sensorId + + ", user: " + userAuthInfo.userId); + final VerifyCredentialResponse response = spManager.verifyChallengeInternal( + getGatekeeperService(), userAuthInfo.gatekeeperPassword, challenge, + userAuthInfo.userId); + if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { + Slog.wtf(TAG, "VerifyChallenge failed, response: " + + response.getResponseCode()); + } + faceManager.resetLockout(sensorId, userAuthInfo.userId, + response.getGatekeeperHAT()); + } + + sensorIds.remove(sensorId); + faceManager.revokeChallenge(sensorId); + + if (sensorIds.isEmpty()) { + Slog.d(TAG, "Done requesting resetLockout for all face sensors"); + finishCallback.onFinished(); + } + } + + synchronized IGateKeeperService getGatekeeperService() { + final IBinder service = ServiceManager.getService(Context.GATEKEEPER_SERVICE); + if (service == null) { + Slog.e(TAG, "Unable to acquire GateKeeperService"); + return null; + } + return IGateKeeperService.Stub.asInterface(service); + } + } + + @Nullable private FaceResetLockoutTask mFaceResetLockoutTask; + + private final FaceResetLockoutTask.FinishCallback mFaceFinishCallback = () -> { + mFaceResetLockoutTask = null; + }; + + BiometricDeferredQueue(@NonNull Context context, @NonNull SyntheticPasswordManager spManager, + @NonNull Handler handler) { + mContext = context; + mSpManager = spManager; + mHandler = handler; + mPendingResetLockouts = new ArrayList<>(); + } + + public void systemReady(@Nullable FingerprintManager fingerprintManager, + @Nullable FaceManager faceManager) { + mFingerprintManager = fingerprintManager; + mFaceManager = faceManager; + } + + /** + * Adds a request for resetLockout on all biometric sensors for the user specified. The queue + * owner must invoke {@link #processPendingLockoutResets()} at some point to kick off the + * operations. + * + * Note that this should only ever be invoked for successful authentications, otherwise it will + * consume a Gatekeeper authentication attempt and potentially wipe the user/device. + * + * @param userId The user that the operation will apply for. + * @param gatekeeperPassword The Gatekeeper Password + */ + void addPendingLockoutResetForUser(int userId, @NonNull byte[] gatekeeperPassword) { + mHandler.post(() -> { + Slog.d(TAG, "addPendingLockoutResetForUser: " + userId); + mPendingResetLockouts.add(new UserAuthInfo(userId, gatekeeperPassword)); + }); + } + + void processPendingLockoutResets() { + mHandler.post(() -> { + Slog.d(TAG, "processPendingLockoutResets: " + mPendingResetLockouts.size()); + processPendingLockoutsForFingerprint(new ArrayList<>(mPendingResetLockouts)); + processPendingLockoutsForFace(new ArrayList<>(mPendingResetLockouts)); + mPendingResetLockouts.clear(); + }); + } + + private void processPendingLockoutsForFingerprint(List<UserAuthInfo> pendingResetLockouts) { + if (mFingerprintManager != null) { + final List<FingerprintSensorProperties> fingerprintSensorProperties = + mFingerprintManager.getSensorProperties(); + for (FingerprintSensorProperties prop : fingerprintSensorProperties) { + if (!prop.resetLockoutRequiresHardwareAuthToken) { + for (UserAuthInfo user : pendingResetLockouts) { + mFingerprintManager.resetLockout(prop.sensorId, user.userId, + null /* hardwareAuthToken */); + } + } else { + Slog.e(TAG, "Fingerprint resetLockout with HAT not supported yet"); + // TODO(b/152414803): Implement this when resetLockout is implemented below + // the framework. + } + } + } + } + + /** + * For devices on {@link android.hardware.biometrics.face.V1_0} which only support a single + * in-flight challenge, we generate a single challenge to reset lockout for all profiles. This + * hopefully reduces/eliminates issues such as overwritten challenge, incorrectly revoked + * challenge, or other race conditions. + * + * TODO(b/162965646) This logic can be avoided if multiple in-flight challenges are supported. + * Though it will need to continue to exist to support existing HIDLs, each profile that + * requires resetLockout could have its own challenge, and the `mPendingResetLockouts` queue + * can be avoided. + */ + private void processPendingLockoutsForFace(List<UserAuthInfo> pendingResetLockouts) { + if (mFaceManager != null) { + if (mFaceResetLockoutTask != null) { + // This code will need to be updated if this problem ever occurs. + Slog.w(TAG, "mFaceGenerateChallengeCallback not null, previous operation may be" + + " stuck"); + } + final List<FaceSensorProperties> faceSensorProperties = + mFaceManager.getSensorProperties(); + final Set<Integer> sensorIds = new ArraySet<>(); + for (FaceSensorProperties prop : faceSensorProperties) { + sensorIds.add(prop.sensorId); + } + + mFaceResetLockoutTask = new FaceResetLockoutTask(mFaceFinishCallback, mFaceManager, + mSpManager, sensorIds, pendingResetLockouts); + for (final FaceSensorProperties prop : faceSensorProperties) { + // Generate a challenge for each sensor. The challenge does not need to be + // per-user, since the HAT returned by gatekeeper contains userId. + mFaceManager.generateChallenge(prop.sensorId, mFaceResetLockoutTask); + } + } + } +} diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index d6e37bacdba8..0044d8936841 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -37,7 +37,6 @@ import static com.android.internal.widget.LockPatternUtils.VERIFY_FLAG_RETURN_GK import static com.android.internal.widget.LockPatternUtils.frpCredentialEnabled; import static com.android.internal.widget.LockPatternUtils.userOwnsFrpCredential; -import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; @@ -187,23 +186,6 @@ public class LockSettingsService extends ILockSettings.Stub { private static final String SYNTHETIC_PASSWORD_UPDATE_TIME_KEY = "sp-handle-ts"; private static final String USER_SERIAL_NUMBER_KEY = "serial-number"; - // TODO (b/145978626) LockSettingsService no longer accepts challenges in the verifyCredential - // paths. These are temporarily left around to ensure that resetLockout works. It will be - // removed once resetLockout is compartmentalized. - // No challenge provided - private static final int CHALLENGE_NONE = 0; - // Challenge was provided from the external caller (non-LockSettingsService) - private static final int CHALLENGE_FROM_CALLER = 1; - // Challenge was generated from within LockSettingsService, for resetLockout. When challenge - // type is set to internal, LSS will revokeChallenge after all profiles for that user are - // unlocked. - private static final int CHALLENGE_INTERNAL = 2; - - @IntDef({CHALLENGE_NONE, - CHALLENGE_FROM_CALLER, - CHALLENGE_INTERNAL}) - @interface ChallengeType {} - // Order of holding lock: mSeparateChallengeLock -> mSpManager -> this // Do not call into ActivityManager while holding mSpManager lock. private final Object mSeparateChallengeLock = new Object(); @@ -219,6 +201,7 @@ public class LockSettingsService extends ILockSettings.Stub { protected final LockSettingsStorage mStorage; private final LockSettingsStrongAuth mStrongAuth; private final SynchronizedStrongAuthTracker mStrongAuthTracker; + private final BiometricDeferredQueue mBiometricDeferredQueue; private final NotificationManager mNotificationManager; private final UserManager mUserManager; @@ -321,15 +304,6 @@ public class LockSettingsService extends ILockSettings.Stub { } } - private class PendingResetLockout { - final int mUserId; - final byte[] mHAT; - PendingResetLockout(int userId, byte[] hat) { - mUserId = userId; - mHAT = hat; - } - } - private LockscreenCredential generateRandomProfilePassword() { byte[] randomLockSeed = new byte[] {}; try { @@ -588,6 +562,7 @@ public class LockSettingsService extends ILockSettings.Stub { mSpManager = injector.getSyntheticPasswordManager(mStorage); mManagedProfilePasswordCache = injector.getManagedProfilePasswordCache(); + mBiometricDeferredQueue = new BiometricDeferredQueue(mContext, mSpManager, mHandler); mRebootEscrowManager = injector.getRebootEscrowManager(new RebootEscrowCallbacks(), mStorage); @@ -740,8 +715,7 @@ public class LockSettingsService extends ILockSettings.Stub { // If boot took too long and the password in vold got expired, parent keystore will // be still locked, we ignore this case since the user will be prompted to unlock // the device after boot. - unlockChildProfile(userId, true /* ignoreUserNotAuthenticated */, - CHALLENGE_NONE, 0 /* challenge */, null /* resetLockouts */); + unlockChildProfile(userId, true /* ignoreUserNotAuthenticated */); } } @@ -830,6 +804,8 @@ public class LockSettingsService extends ILockSettings.Stub { mRebootEscrowManager.loadRebootEscrowDataIfAvailable(); // TODO: maybe skip this for split system user mode. mStorage.prefetchUser(UserHandle.USER_SYSTEM); + mBiometricDeferredQueue.systemReady(mInjector.getFingerprintManager(), + mInjector.getFaceManager()); } private void getAuthSecretHal() { @@ -1306,13 +1282,10 @@ public class LockSettingsService extends ILockSettings.Stub { return credential; } - private void unlockChildProfile(int profileHandle, boolean ignoreUserNotAuthenticated, - @ChallengeType int challengeType, long challenge, - @Nullable ArrayList<PendingResetLockout> resetLockouts) { + private void unlockChildProfile(int profileHandle, boolean ignoreUserNotAuthenticated) { try { doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle), - challengeType, challenge, profileHandle, null /* progressCallback */, - resetLockouts, 0 /* flags */); + profileHandle, null /* progressCallback */, 0 /* flags */); } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | IllegalBlockSizeException @@ -1327,10 +1300,6 @@ public class LockSettingsService extends ILockSettings.Stub { } } - private void unlockUser(int userId, byte[] token, byte[] secret) { - unlockUser(userId, token, secret, CHALLENGE_NONE, 0 /* challenge */, null); - } - /** * Unlock the user (both storage and user state) and its associated managed profiles * synchronously. @@ -1339,9 +1308,7 @@ public class LockSettingsService extends ILockSettings.Stub { * can end up calling into other system services to process user unlock request (via * {@link com.android.server.SystemServiceManager#unlockUser} </em> */ - private void unlockUser(int userId, byte[] token, byte[] secret, - @ChallengeType int challengeType, long challenge, - @Nullable ArrayList<PendingResetLockout> resetLockouts) { + private void unlockUser(int userId, byte[] token, byte[] secret) { Slog.i(TAG, "Unlocking user " + userId + " with secret only, length " + (secret != null ? secret.length : 0)); // TODO: make this method fully async so we can update UI with progress strings @@ -1378,6 +1345,9 @@ public class LockSettingsService extends ILockSettings.Stub { } if (mUserManager.getUserInfo(userId).isManagedProfile()) { + if (!hasUnifiedChallenge(userId)) { + mBiometricDeferredQueue.processPendingLockoutResets(); + } return; } @@ -1388,10 +1358,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (hasUnifiedChallenge(profile.id)) { if (mUserManager.isUserRunning(profile.id)) { // Unlock managed profile with unified lock - // Must pass the challenge on for resetLockout, so it's not over-written, which - // causes LockSettingsService to revokeChallenge inappropriately. - unlockChildProfile(profile.id, false /* ignoreUserNotAuthenticated */, - challengeType, challenge, resetLockouts); + unlockChildProfile(profile.id, false /* ignoreUserNotAuthenticated */); } else { try { // Profile not ready for unlock yet, but decrypt the unified challenge now @@ -1412,22 +1379,9 @@ public class LockSettingsService extends ILockSettings.Stub { restoreCallingIdentity(ident); } } - } - if (resetLockouts != null && !resetLockouts.isEmpty()) { - mHandler.post(() -> { - final BiometricManager bm = mContext.getSystemService(BiometricManager.class); - final PackageManager pm = mContext.getPackageManager(); - for (int i = 0; i < resetLockouts.size(); i++) { - bm.resetLockout(resetLockouts.get(i).mUserId, resetLockouts.get(i).mHAT); - } - if (challengeType == CHALLENGE_INTERNAL - && pm.hasSystemFeature(PackageManager.FEATURE_FACE)) { - mContext.getSystemService(FaceManager.class).revokeChallenge(); - } - }); - } + mBiometricDeferredQueue.processPendingLockoutResets(); } private boolean hasUnifiedChallenge(int userId) { @@ -1727,8 +1681,7 @@ public class LockSettingsService extends ILockSettings.Stub { setUserKeyProtection(userId, credential, convertResponse(gkResponse)); fixateNewestUserKeyAuth(userId); // Refresh the auth token - doVerifyCredential(credential, CHALLENGE_FROM_CALLER, 0, userId, - null /* progressCallback */, 0 /* flags */); + doVerifyCredential(credential, userId, null /* progressCallback */, 0 /* flags */); synchronizeUnifiedWorkChallengeForProfiles(userId, null); sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent); return true; @@ -1972,8 +1925,7 @@ public class LockSettingsService extends ILockSettings.Stub { ICheckCredentialProgressCallback progressCallback) { checkPasswordReadPermission(userId); try { - return doVerifyCredential(credential, CHALLENGE_NONE, 0L, userId, progressCallback, - 0 /* flags */); + return doVerifyCredential(credential, userId, progressCallback, 0 /* flags */); } finally { scheduleGc(); } @@ -1984,10 +1936,8 @@ public class LockSettingsService extends ILockSettings.Stub { public VerifyCredentialResponse verifyCredential(LockscreenCredential credential, int userId, int flags) { checkPasswordReadPermission(userId); - try { - return doVerifyCredential(credential, CHALLENGE_NONE, 0L, userId, - null /* progressCallback */, flags); + return doVerifyCredential(credential, userId, null /* progressCallback */, flags); } finally { scheduleGc(); } @@ -2006,32 +1956,17 @@ public class LockSettingsService extends ILockSettings.Stub { return response; } - /** + /* + * Verify user credential and unlock the user. Fix pattern bug by deprecating the old base zero + * format. * @param credential User's lockscreen credential - * @param challengeType Owner of the challenge - * @param challenge Challenge to be wrapped within Gatekeeper's HAT, if the credential is - * verified * @param userId User to verify the credential for * @param progressCallback Receive progress callbacks * @param flags See {@link LockPatternUtils.VerifyFlag} * @return See {@link VerifyCredentialResponse} */ private VerifyCredentialResponse doVerifyCredential(LockscreenCredential credential, - @ChallengeType int challengeType, long challenge, int userId, - ICheckCredentialProgressCallback progressCallback, - @LockPatternUtils.VerifyFlag int flags) { - return doVerifyCredential(credential, challengeType, challenge, userId, - progressCallback, null /* resetLockouts */, flags); - } - - /** - * Verify user credential and unlock the user. Fix pattern bug by deprecating the old base zero - * format. - */ - private VerifyCredentialResponse doVerifyCredential(LockscreenCredential credential, - @ChallengeType int challengeType, long challenge, int userId, - ICheckCredentialProgressCallback progressCallback, - @Nullable ArrayList<PendingResetLockout> resetLockouts, + int userId, ICheckCredentialProgressCallback progressCallback, @LockPatternUtils.VerifyFlag int flags) { if (credential == null || credential.isNone()) { throw new IllegalArgumentException("Credential can't be null or empty"); @@ -2041,9 +1976,10 @@ public class LockSettingsService extends ILockSettings.Stub { Slog.e(TAG, "FRP credential can only be verified prior to provisioning."); return VerifyCredentialResponse.ERROR; } - VerifyCredentialResponse response = null; - response = spBasedDoVerifyCredential(credential, challengeType, challenge, - userId, progressCallback, resetLockouts, flags); + + VerifyCredentialResponse response = spBasedDoVerifyCredential(credential, userId, + progressCallback, flags); + // The user employs synthetic password based credential. if (response != null) { if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { @@ -2064,8 +2000,7 @@ public class LockSettingsService extends ILockSettings.Stub { return VerifyCredentialResponse.ERROR; } - response = verifyCredential(userId, storedHash, credential, - challengeType, challenge, progressCallback); + response = verifyCredential(userId, storedHash, credential, progressCallback); if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { mStrongAuth.reportSuccessfulStrongAuthUnlock(userId); @@ -2085,8 +2020,6 @@ public class LockSettingsService extends ILockSettings.Stub { // Unlock parent by using parent's challenge final VerifyCredentialResponse parentResponse = doVerifyCredential( credential, - CHALLENGE_NONE, - 0L, parentProfileId, null /* progressCallback */, flags); @@ -2098,10 +2031,7 @@ public class LockSettingsService extends ILockSettings.Stub { try { // Unlock work profile, and work profile with unified lock must use password only return doVerifyCredential(getDecryptedPasswordForTiedProfile(userId), - CHALLENGE_NONE, - 0L, - userId, null /* progressCallback */, - flags); + userId, null /* progressCallback */, flags); } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | IllegalBlockSizeException @@ -2119,8 +2049,7 @@ public class LockSettingsService extends ILockSettings.Stub { * hash to GK. */ private VerifyCredentialResponse verifyCredential(int userId, CredentialHash storedHash, - LockscreenCredential credential, @ChallengeType int challengeType, long challenge, - ICheckCredentialProgressCallback progressCallback) { + LockscreenCredential credential, ICheckCredentialProgressCallback progressCallback) { if ((storedHash == null || storedHash.hash.length == 0) && credential.isNone()) { // don't need to pass empty credentials to GateKeeper return VerifyCredentialResponse.OK; @@ -2137,7 +2066,7 @@ public class LockSettingsService extends ILockSettings.Stub { GateKeeperResponse gateKeeperResponse; try { gateKeeperResponse = getGateKeeperService().verifyChallenge( - userId, challenge, storedHash.hash, credential.getCredential()); + userId, 0L /* challenge */, storedHash.hash, credential.getCredential()); } catch (RemoteException e) { Slog.e(TAG, "gatekeeper verify failed", e); gateKeeperResponse = GateKeeperResponse.ERROR; @@ -2710,28 +2639,13 @@ public class LockSettingsService extends ILockSettings.Stub { } private VerifyCredentialResponse spBasedDoVerifyCredential(LockscreenCredential userCredential, - @ChallengeType int challengeType, long challenge, int userId, ICheckCredentialProgressCallback progressCallback, - @Nullable ArrayList<PendingResetLockout> resetLockouts, @LockPatternUtils.VerifyFlag int flags) { - final boolean hasEnrolledBiometrics = mInjector.hasEnrolledBiometrics(userId); - Slog.d(TAG, "spBasedDoVerifyCredential: user=" + userId + " challengeType=" + challengeType + Slog.d(TAG, "spBasedDoVerifyCredential: user=" + userId + " hasEnrolledBiometrics=" + hasEnrolledBiometrics); - final PackageManager pm = mContext.getPackageManager(); - // TODO: When lockout is handled under the HAL for all biometrics (fingerprint), - // we need to generate challenge for each one, have it signed by GK and reset lockout - // for each modality. - if (challengeType == CHALLENGE_NONE && pm.hasSystemFeature(PackageManager.FEATURE_FACE) - && hasEnrolledBiometrics) { - // If there are multiple profiles in the same account, ensure we only generate the - // challenge once. - challengeType = CHALLENGE_INTERNAL; - challenge = mContext.getSystemService(FaceManager.class).generateChallengeBlocking(); - } - final AuthenticationResult authResult; VerifyCredentialResponse response; final boolean returnGkPw = (flags & VERIFY_FLAG_RETURN_GK_PW) != 0; @@ -2752,10 +2666,13 @@ public class LockSettingsService extends ILockSettings.Stub { // credential has matched if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { + mBiometricDeferredQueue.addPendingLockoutResetForUser(userId, + authResult.authToken.deriveGkPassword()); + // perform verifyChallenge with synthetic password which generates the real GK auth // token and response for the current user response = mSpManager.verifyChallenge(getGateKeeperService(), authResult.authToken, - challenge, userId); + 0L /* challenge */, userId); if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { // This shouldn't really happen: the unwrapping of SP succeeds, but SP doesn't // match the recorded GK password handle. @@ -2765,15 +2682,7 @@ public class LockSettingsService extends ILockSettings.Stub { } } if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { - // Do resetLockout / revokeChallenge when all profiles are unlocked - if (hasEnrolledBiometrics) { - if (resetLockouts == null) { - resetLockouts = new ArrayList<>(); - } - resetLockouts.add(new PendingResetLockout(userId, response.getGatekeeperHAT())); - } - - onCredentialVerified(authResult.authToken, challengeType, challenge, resetLockouts, + onCredentialVerified(authResult.authToken, PasswordMetrics.computeForCredential(userCredential), userId); } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) { if (response.getTimeout() > 0) { @@ -2789,9 +2698,7 @@ public class LockSettingsService extends ILockSettings.Stub { } } - private void onCredentialVerified(AuthenticationToken authToken, - @ChallengeType int challengeType, long challenge, - @Nullable ArrayList<PendingResetLockout> resetLockouts, PasswordMetrics metrics, + private void onCredentialVerified(AuthenticationToken authToken, PasswordMetrics metrics, int userId) { if (metrics != null) { @@ -2806,7 +2713,7 @@ public class LockSettingsService extends ILockSettings.Stub { { final byte[] secret = authToken.deriveDiskEncryptionKey(); - unlockUser(userId, null, secret, challengeType, challenge, resetLockouts); + unlockUser(userId, null, secret); Arrays.fill(secret, (byte) 0); } activateEscrowTokens(authToken, userId); @@ -3193,11 +3100,8 @@ public class LockSettingsService extends ILockSettings.Stub { return false; } } - // TODO: Reset biometrics lockout here. Ideally that should be self-contained inside - // onCredentialVerified(), which will require some refactoring on the current lockout - // reset logic. - onCredentialVerified(authResult.authToken, CHALLENGE_NONE, 0, null, + onCredentialVerified(authResult.authToken, loadPasswordMetrics(authResult.authToken, userId), userId); return true; } @@ -3208,8 +3112,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (cred == null) { return false; } - return doVerifyCredential(cred, CHALLENGE_NONE, 0, userId, - null /* progressCallback */, 0 /* flags */) + return doVerifyCredential(cred, userId, null /* progressCallback */, 0 /* flags */) .getResponseCode() == VerifyCredentialResponse.RESPONSE_OK; } } @@ -3532,8 +3435,7 @@ public class LockSettingsService extends ILockSettings.Stub { SyntheticPasswordManager.AuthenticationToken authToken = new SyntheticPasswordManager.AuthenticationToken(spVersion); authToken.recreateDirectly(syntheticPassword); - onCredentialVerified(authToken, CHALLENGE_NONE, 0, null, - loadPasswordMetrics(authToken, userId), userId); + onCredentialVerified(authToken, loadPasswordMetrics(authToken, userId), userId); } } } diff --git a/services/core/java/com/android/server/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java index 3a4dfaf9bfcd..0b3cdae9231e 100644 --- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java +++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java @@ -34,6 +34,7 @@ import android.content.IntentFilter; import android.media.AudioManager; import android.media.AudioSystem; import android.media.MediaRoute2Info; +import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; import android.util.Slog; @@ -55,7 +56,6 @@ class BluetoothRouteProvider { private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final String HEARING_AID_ROUTE_ID_PREFIX = "HEARING_AID_"; - private static BluetoothRouteProvider sInstance; @SuppressWarnings("WeakerAccess") /* synthetic access */ // Maps hardware address to BluetoothRouteInfo @@ -79,19 +79,21 @@ class BluetoothRouteProvider { private final BroadcastReceiver mBroadcastReceiver = new BluetoothBroadcastReceiver(); private final BluetoothProfileListener mProfileListener = new BluetoothProfileListener(); - static synchronized BluetoothRouteProvider getInstance(@NonNull Context context, + /** + * Create an instance of {@link BluetoothRouteProvider}. + * It may return {@code null} if Bluetooth is not supported on this hardware platform. + */ + @Nullable + static BluetoothRouteProvider createInstance(@NonNull Context context, @NonNull BluetoothRoutesUpdatedListener listener) { Objects.requireNonNull(context); Objects.requireNonNull(listener); - if (sInstance == null) { - BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); - if (btAdapter == null) { - return null; - } - sInstance = new BluetoothRouteProvider(context, btAdapter, listener); + BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); + if (btAdapter == null) { + return null; } - return sInstance; + return new BluetoothRouteProvider(context, btAdapter, listener); } private BluetoothRouteProvider(Context context, BluetoothAdapter btAdapter, @@ -103,7 +105,7 @@ class BluetoothRouteProvider { buildBluetoothRoutes(); } - public void start() { + public void start(UserHandle user) { mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.A2DP); mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEARING_AID); @@ -118,7 +120,8 @@ class BluetoothRouteProvider { addEventReceiver(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED, deviceStateChangedReceiver); - mContext.registerReceiver(mBroadcastReceiver, mIntentFilter, null, null); + mContext.registerReceiverAsUser(mBroadcastReceiver, user, + mIntentFilter, null, null); } /** diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 875bfdffafcd..1114fe0d9bf8 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -1176,7 +1176,8 @@ class MediaRouter2ServiceImpl { super(Looper.getMainLooper(), null, true); mServiceRef = new WeakReference<>(service); mUserRecord = userRecord; - mSystemProvider = new SystemMediaRoute2Provider(service.mContext); + mSystemProvider = new SystemMediaRoute2Provider(service.mContext, + UserHandle.of(userRecord.mUserId)); mRouteProviders.add(mSystemProvider); mWatcher = new MediaRoute2ProviderWatcher(service.mContext, this, this, mUserRecord.mUserId); diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 0f6748366e16..8777ceacf884 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -589,11 +589,19 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR if (mDestroyed) { return; } + ParceledListSlice<QueueItem> parcelableQueue; + if (mQueue == null) { + parcelableQueue = null; + } else { + parcelableQueue = new ParceledListSlice<>(mQueue); + // Limit the size of initial Parcel to prevent binder buffer overflow + // as onQueueChanged is an async binder call. + parcelableQueue.setInlineCountLimit(1); + } for (int i = mControllerCallbackHolders.size() - 1; i >= 0; i--) { ISessionControllerCallbackHolder holder = mControllerCallbackHolders.get(i); try { - holder.mCallback.onQueueChanged(mQueue == null ? null : - new ParceledListSlice<>(mQueue)); + holder.mCallback.onQueueChanged(parcelableQueue); } catch (DeadObjectException e) { mControllerCallbackHolders.remove(i); logCallbackException("Removing dead callback in pushQueueUpdate", holder, e); diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index eb4ab1ceac28..a8a0e2e937d0 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -32,14 +32,15 @@ import android.app.KeyguardManager; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.ActivityNotFoundException; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.content.pm.UserInfo; -import android.database.ContentObserver; import android.media.AudioManager; import android.media.AudioManagerInternal; import android.media.AudioPlaybackConfiguration; @@ -58,7 +59,6 @@ import android.media.session.ISessionManager; import android.media.session.MediaController; import android.media.session.MediaSession; import android.media.session.MediaSessionManager; -import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Handler; @@ -138,7 +138,6 @@ public class MediaSessionService extends SystemService implements Monitor { private KeyguardManager mKeyguardManager; private AudioManagerInternal mAudioManagerInternal; private ContentResolver mContentResolver; - private SettingsObserver mSettingsObserver; private boolean mHasFeatureLeanback; // The FullUserRecord of the current users. (i.e. The foreground user that isn't a profile) @@ -192,8 +191,6 @@ public class MediaSessionService extends SystemService implements Monitor { } }, null /* handler */); mContentResolver = mContext.getContentResolver(); - mSettingsObserver = new SettingsObserver(); - mSettingsObserver.observe(); mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_LEANBACK); @@ -202,8 +199,20 @@ public class MediaSessionService extends SystemService implements Monitor { instantiateCustomProvider(null); instantiateCustomDispatcher(null); mRecordThread.start(); + + final IntentFilter filter = new IntentFilter( + NotificationManager.ACTION_NOTIFICATION_LISTENER_ENABLED_CHANGED); + mContext.registerReceiver(mNotificationListenerEnabledChangedReceiver, filter); } + private final BroadcastReceiver mNotificationListenerEnabledChangedReceiver = + new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + updateActiveSessionListeners(); + } + }; + private boolean isGlobalPriorityActiveLocked() { return mGlobalPrioritySession != null && mGlobalPrioritySession.isActive(); } @@ -1082,25 +1091,6 @@ public class MediaSessionService extends SystemService implements Monitor { } } - final class SettingsObserver extends ContentObserver { - private final Uri mSecureSettingsUri = Settings.Secure.getUriFor( - Settings.Secure.ENABLED_NOTIFICATION_LISTENERS); - - private SettingsObserver() { - super(null); - } - - private void observe() { - mContentResolver.registerContentObserver(mSecureSettingsUri, - false, this, ALL.getIdentifier()); - } - - @Override - public void onChange(boolean selfChange, Uri uri) { - updateActiveSessionListeners(); - } - } - class SessionManagerImpl extends ISessionManager.Stub { private static final String EXTRA_WAKELOCK_ACQUIRED = "android.media.AudioService.WAKELOCK_ACQUIRED"; @@ -2710,5 +2700,4 @@ public class MediaSessionService extends SystemService implements Monitor { obtainMessage(msg, userIdInteger).sendToTarget(); } } - } diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java index 953aae44d6a7..d9b5b6d41c11 100644 --- a/services/core/java/com/android/server/media/MediaSessionStack.java +++ b/services/core/java/com/android/server/media/MediaSessionStack.java @@ -20,7 +20,6 @@ import static com.android.server.media.SessionPolicyProvider.SESSION_POLICY_IGNO import android.media.Session2Token; import android.media.session.MediaSession; -import android.os.Debug; import android.os.UserHandle; import android.util.Log; import android.util.SparseArray; @@ -187,7 +186,7 @@ class MediaSessionStack { */ public void updateMediaButtonSessionIfNeeded() { if (DEBUG) { - Log.d(TAG, "updateMediaButtonSessionIfNeeded, callers=" + Debug.getCallers(2)); + Log.d(TAG, "updateMediaButtonSessionIfNeeded, callers=" + getCallers(2)); } List<Integer> audioPlaybackUids = mAudioPlayerStateMonitor.getSortedAudioPlaybackClientUids(); @@ -413,4 +412,24 @@ class MediaSessionStack { // so they also need to be cleared. mCachedActiveLists.remove(UserHandle.USER_ALL); } + + // Code copied from android.os.Debug#getCallers(int) + private static String getCallers(final int depth) { + final StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < depth; i++) { + sb.append(getCaller(callStack, i)).append(" "); + } + return sb.toString(); + } + + // Code copied from android.os.Debug#getCaller(StackTraceElement[], int) + private static String getCaller(StackTraceElement[] callStack, int depth) { + // callStack[4] is the caller of the method that called getCallers() + if (4 + depth >= callStack.length) { + return "<bottom of call stack>"; + } + StackTraceElement caller = callStack[4 + depth]; + return caller.getClassName() + "." + caller.getMethodName() + ":" + caller.getLineNumber(); + } } diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java index 2c089ca8300e..4f7af9469668 100644 --- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java +++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java @@ -45,6 +45,7 @@ import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; import android.util.Slog; @@ -99,7 +100,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { } }; - SystemMediaRoute2Provider(Context context) { + SystemMediaRoute2Provider(Context context, UserHandle user) { super(sComponentName); mIsSystemRouteProvider = true; @@ -117,7 +118,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { updateDeviceRoute(newAudioRoutes); // .getInstance returns null if there is no bt adapter available - mBtRouteProvider = BluetoothRouteProvider.getInstance(context, (routes) -> { + mBtRouteProvider = BluetoothRouteProvider.createInstance(context, (routes) -> { publishProviderState(); boolean sessionInfoChanged; @@ -130,11 +131,12 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { IntentFilter intentFilter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION); intentFilter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION); - mContext.registerReceiver(new AudioManagerBroadcastReceiver(), intentFilter); + mContext.registerReceiverAsUser(new AudioManagerBroadcastReceiver(), user, + intentFilter, null, null); if (mBtRouteProvider != null) { mHandler.post(() -> { - mBtRouteProvider.start(); + mBtRouteProvider.start(user); notifyProviderState(); }); } diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 295143e76235..29ee8eb13564 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -4367,7 +4367,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // Flip state because app was explicitly added or removed to denylist. setMeteredNetworkDenylist(uid, (isDenylisted || isRestrictedByAdmin)); if (hasRule(oldRule, RULE_REJECT_METERED) && isAllowlisted) { - // Since dneylist prevails over allowlist, we need to handle the special case + // Since denylist prevails over allowlist, we need to handle the special case // where app is allowlisted and denylisted at the same time (although such // scenario should be blocked by the UI), then denylist is removed. setMeteredNetworkAllowlist(uid, isAllowlisted); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 52928dc45131..9f9235dc852f 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -31,6 +31,7 @@ import static android.app.NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED import static android.app.NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED_INTERNAL; import static android.app.NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED; import static android.app.NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED; +import static android.app.NotificationManager.ACTION_NOTIFICATION_LISTENER_ENABLED_CHANGED; import static android.app.NotificationManager.ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED; import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL; import static android.app.NotificationManager.EXTRA_AUTOMATIC_ZEN_RULE_ID; @@ -9180,6 +9181,17 @@ public class NotificationManagerService extends SystemService { } @Override + protected void setPackageOrComponentEnabled(String pkgOrComponent, int userId, + boolean isPrimary, boolean enabled) { + super.setPackageOrComponentEnabled(pkgOrComponent, userId, isPrimary, enabled); + + getContext().sendBroadcastAsUser( + new Intent(ACTION_NOTIFICATION_LISTENER_ENABLED_CHANGED) + .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY), + UserHandle.ALL, null); + } + + @Override protected void loadDefaultsFromConfig() { String defaultListenerAccess = mContext.getResources().getString( R.string.config_defaultListenerAccessPackages); diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java index def9c78f98c7..3d7c978ca625 100644 --- a/services/core/java/com/android/server/pm/AppsFilter.java +++ b/services/core/java/com/android/server/pm/AppsFilter.java @@ -35,9 +35,6 @@ import android.content.pm.parsing.component.ParsedInstrumentation; import android.content.pm.parsing.component.ParsedIntentInfo; import android.content.pm.parsing.component.ParsedMainComponent; import android.content.pm.parsing.component.ParsedProvider; -import android.os.Handler; -import android.os.HandlerExecutor; -import android.os.HandlerThread; import android.os.Process; import android.os.Trace; import android.os.UserHandle; @@ -353,13 +350,9 @@ public class AppsFilter { injector.getUserManagerInternal().getUserInfos()); } }; - HandlerThread appsFilterThread = new HandlerThread("appsFilter"); - appsFilterThread.start(); - Handler appsFilterHandler = new Handler(appsFilterThread.getLooper()); - Executor executor = new HandlerExecutor(appsFilterHandler); - AppsFilter appsFilter = new AppsFilter(stateProvider, featureConfig, - forcedQueryablePackageNames, forceSystemAppsQueryable, null, executor); + forcedQueryablePackageNames, forceSystemAppsQueryable, null, + injector.getBackgroundExecutor()); featureConfig.setAppsFilter(appsFilter); return appsFilter; } diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 672ad5e59428..cd383b9d1d7a 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -23,6 +23,8 @@ import android.annotation.UserIdInt; import android.content.Context; import android.content.pm.PackageStats; import android.os.Build; +import android.os.CreateAppDataArgs; +import android.os.CreateAppDataResult; import android.os.IBinder; import android.os.IBinder.DeathRecipient; import android.os.IInstalld; @@ -39,7 +41,10 @@ import dalvik.system.BlockGuard; import dalvik.system.VMRuntime; import java.io.FileDescriptor; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CompletableFuture; public class Installer extends SystemService { private static final String TAG = "Installer"; @@ -176,37 +181,140 @@ public class Installer extends SystemService { } } + private static CreateAppDataArgs buildCreateAppDataArgs(String uuid, String packageName, + int userId, int flags, int appId, String seInfo, int targetSdkVersion) { + final CreateAppDataArgs args = new CreateAppDataArgs(); + args.uuid = uuid; + args.packageName = packageName; + args.userId = userId; + args.flags = flags; + args.appId = appId; + args.seInfo = seInfo; + args.targetSdkVersion = targetSdkVersion; + return args; + } + + private static CreateAppDataResult buildPlaceholderCreateAppDataResult() { + final CreateAppDataResult result = new CreateAppDataResult(); + result.ceDataInode = -1; + result.exceptionCode = 0; + result.exceptionMessage = null; + return result; + } + + /** + * @deprecated callers are encouraged to migrate to using {@link Batch} to + * more efficiently handle operations in bulk. + */ + @Deprecated public long createAppData(String uuid, String packageName, int userId, int flags, int appId, String seInfo, int targetSdkVersion) throws InstallerException { - if (!checkBeforeRemote()) return -1; + final CreateAppDataArgs args = buildCreateAppDataArgs(uuid, packageName, userId, flags, + appId, seInfo, targetSdkVersion); + final CreateAppDataResult result = createAppData(args); + if (result.exceptionCode == 0) { + return result.ceDataInode; + } else { + throw new InstallerException(result.exceptionMessage); + } + } + + public @NonNull CreateAppDataResult createAppData(@NonNull CreateAppDataArgs args) + throws InstallerException { + if (!checkBeforeRemote()) { + return buildPlaceholderCreateAppDataResult(); + } try { - return mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo, - targetSdkVersion); + return mInstalld.createAppData(args); + } catch (Exception e) { + throw InstallerException.from(e); + } + } + + public @NonNull CreateAppDataResult[] createAppDataBatched(@NonNull CreateAppDataArgs[] args) + throws InstallerException { + if (!checkBeforeRemote()) { + final CreateAppDataResult[] results = new CreateAppDataResult[args.length]; + Arrays.fill(results, buildPlaceholderCreateAppDataResult()); + return results; + } + try { + return mInstalld.createAppDataBatched(args); } catch (Exception e) { throw InstallerException.from(e); } } /** - * Batched version of createAppData for use with multiple packages. + * Class that collects multiple {@code installd} operations together in an + * attempt to more efficiently execute them in bulk. + * <p> + * Instead of returning results immediately, {@link CompletableFuture} + * instances are returned which can be used to chain follow-up work for each + * request. + * <p> + * The creator of this object <em>must</em> invoke {@link #execute()} + * exactly once to begin execution of all pending operations. Once execution + * has been kicked off, no additional events can be enqueued into this + * instance, but multiple instances can safely exist in parallel. */ - public void createAppDataBatched(String[] uuids, String[] packageNames, int userId, int flags, - int[] appIds, String[] seInfos, int[] targetSdkVersions) throws InstallerException { - if (!checkBeforeRemote()) return; - final int batchSize = 256; - for (int i = 0; i < uuids.length; i += batchSize) { - int to = i + batchSize; - if (to > uuids.length) { - to = uuids.length; - } - - try { - mInstalld.createAppDataBatched(Arrays.copyOfRange(uuids, i, to), - Arrays.copyOfRange(packageNames, i, to), userId, flags, - Arrays.copyOfRange(appIds, i, to), Arrays.copyOfRange(seInfos, i, to), - Arrays.copyOfRange(targetSdkVersions, i, to)); - } catch (Exception e) { - throw InstallerException.from(e); + public static class Batch { + private static final int CREATE_APP_DATA_BATCH_SIZE = 256; + + private boolean mExecuted; + + private final List<CreateAppDataArgs> mArgs = new ArrayList<>(); + private final List<CompletableFuture<Long>> mFutures = new ArrayList<>(); + + /** + * Enqueue the given {@code installd} operation to be executed in the + * future when {@link #execute(Installer)} is invoked. + * <p> + * Callers of this method are not required to hold a monitor lock on an + * {@link Installer} object. + */ + public synchronized @NonNull CompletableFuture<Long> createAppData(String uuid, + String packageName, int userId, int flags, int appId, String seInfo, + int targetSdkVersion) { + if (mExecuted) throw new IllegalStateException(); + + final CreateAppDataArgs args = buildCreateAppDataArgs(uuid, packageName, userId, flags, + appId, seInfo, targetSdkVersion); + final CompletableFuture<Long> future = new CompletableFuture<>(); + mArgs.add(args); + mFutures.add(future); + return future; + } + + /** + * Execute all pending {@code installd} operations that have been + * collected by this batch in a blocking fashion. + * <p> + * Callers of this method <em>must</em> hold a monitor lock on the given + * {@link Installer} object. + */ + public synchronized void execute(@NonNull Installer installer) throws InstallerException { + if (mExecuted) throw new IllegalStateException(); + mExecuted = true; + + final int size = mArgs.size(); + for (int i = 0; i < size; i += CREATE_APP_DATA_BATCH_SIZE) { + final CreateAppDataArgs[] args = new CreateAppDataArgs[Math.min(size - i, + CREATE_APP_DATA_BATCH_SIZE)]; + for (int j = 0; j < args.length; j++) { + args[j] = mArgs.get(i + j); + } + final CreateAppDataResult[] results = installer.createAppDataBatched(args); + for (int j = 0; j < args.length; j++) { + final CreateAppDataResult result = results[j]; + final CompletableFuture<Long> future = mFutures.get(i + j); + if (result.exceptionCode == 0) { + future.complete(result.ceDataInode); + } else { + future.completeExceptionally( + new InstallerException(result.exceptionMessage)); + } + } } } } diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java index 0b0f13929b2a..79f8dc1c9a1e 100644 --- a/services/core/java/com/android/server/pm/InstantAppResolver.java +++ b/services/core/java/com/android/server/pm/InstantAppResolver.java @@ -380,7 +380,7 @@ public abstract class InstantAppResolver { sanitizeIntent(request.origIntent), // This must only expose the secured version of the host request.hostDigestPrefixSecure, - UserHandle.getUserHandleForUid(request.userId), + UserHandle.of(request.userId), request.isRequesterInstantApp, request.token ); diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 2807a1e4c081..28c5e964fe27 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -1328,12 +1328,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { if (PackageInstaller.STATUS_SUCCESS == status) { mChildSessionsRemaining.removeAt(sessionIndex); if (mChildSessionsRemaining.size() == 0) { - try { - intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, - PackageInstallerSession.this.sessionId); - mStatusReceiver.sendIntent(mContext, 0, intent, null, null); - } catch (IntentSender.SendIntentException ignore) { - } + destroyInternal(); + dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, + "Session installed", null); } } else if (PackageInstaller.STATUS_PENDING_USER_ACTION == status) { try { @@ -1492,53 +1489,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } /** - * Assert multipackage install has consistent sessions. - * - * @throws PackageManagerException if child sessions don't match parent session - * in respect to staged and enable rollback parameters. - */ - @GuardedBy("mLock") - private void assertMultiPackageConsistencyLocked( - @NonNull List<PackageInstallerSession> childSessions) throws PackageManagerException { - for (PackageInstallerSession childSession : childSessions) { - // It might be that the parent session is loaded before all of it's child sessions are, - // e.g. when reading sessions from XML. Those sessions will be null here, and their - // conformance with the multipackage params will be checked when they're loaded. - if (childSession == null) { - continue; - } - assertConsistencyWithLocked(childSession); - } - } - - /** - * Assert consistency with the given session. - * - * @throws PackageManagerException if other sessions doesn't match this session - * in respect to staged and enable rollback parameters. - */ - @GuardedBy("mLock") - private void assertConsistencyWithLocked(PackageInstallerSession other) - throws PackageManagerException { - // Session groups must be consistent wrt to isStaged parameter. Non-staging session - // cannot be grouped with staging sessions. - if (this.params.isStaged != other.params.isStaged) { - throw new PackageManagerException( - PackageManager.INSTALL_FAILED_MULTIPACKAGE_INCONSISTENCY, - "Multipackage Inconsistency: session " + other.sessionId - + " and session " + sessionId - + " have inconsistent staged settings"); - } - if (this.params.getEnableRollback() != other.params.getEnableRollback()) { - throw new PackageManagerException( - PackageManager.INSTALL_FAILED_MULTIPACKAGE_INCONSISTENCY, - "Multipackage Inconsistency: session " + other.sessionId - + " and session " + sessionId - + " have inconsistent rollback settings"); - } - } - - /** * Seal the session to prevent further modification. * * <p>The session will be sealed after calling this method even if it failed. @@ -1552,14 +1502,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { try { assertNoWriteFileTransfersOpenLocked(); assertPreparedAndNotDestroyedLocked("sealing of session"); - mSealed = true; - List<PackageInstallerSession> childSessions = getChildSessionsLocked(); - if (childSessions != null) { - assertMultiPackageConsistencyLocked(childSessions); - } - } catch (PackageManagerException e) { - throw onSessionValidationFailure(e); } catch (Throwable e) { // Convert all exceptions into package manager exceptions as only those are handled // in the code above. @@ -2791,23 +2734,27 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } - @Override - public void abandon() { - if (hasParentSessionId()) { - throw new IllegalStateException( - "Session " + sessionId + " is a child of multi-package session " - + getParentSessionId() + " and may not be abandoned directly."); + private void abandonNonStaged() { + synchronized (mLock) { + assertCallerIsOwnerOrRootLocked(); + if (mRelinquished) { + if (LOGD) Slog.d(TAG, "Ignoring abandon after commit relinquished control"); + return; + } + destroyInternal(); } + dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null); + } + private void abandonStaged() { synchronized (mLock) { - if (params.isStaged && mDestroyed) { + if (mDestroyed) { // If a user abandons staged session in an unsafe state, then system will try to // abandon the destroyed staged session when it is safe on behalf of the user. assertCallerIsOwnerOrRootOrSystemLocked(); } else { assertCallerIsOwnerOrRootLocked(); } - if (isStagedAndInTerminalState()) { // We keep the session in the database if it's in a finalized state. It will be // removed by PackageInstallerService when the last update time is old enough. @@ -2815,26 +2762,35 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // do it now. return; } - if (mCommitted && params.isStaged) { - mDestroyed = true; + mDestroyed = true; + if (mCommitted) { if (!mStagingManager.abortCommittedSessionLocked(this)) { // Do not clean up the staged session from system. It is not safe yet. mCallback.onStagedSessionChanged(this); return; } - cleanStageDir(getChildSessionsLocked()); - } - - if (mRelinquished) { - Slog.d(TAG, "Ignoring abandon after commit relinquished control"); - return; } + cleanStageDir(getChildSessionsLocked()); destroyInternal(); } dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null); } @Override + public void abandon() { + if (hasParentSessionId()) { + throw new IllegalStateException( + "Session " + sessionId + " is a child of multi-package session " + + getParentSessionId() + " and may not be abandoned directly."); + } + if (params.isStaged) { + abandonStaged(); + } else { + abandonNonStaged(); + } + } + + @Override public boolean isMultiPackage() { return params.isMultiPackage; } @@ -3193,6 +3149,16 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { throw new IllegalStateException("Multi-session " + childSessionId + " can't be a child."); } + if (params.isStaged != childSession.params.isStaged) { + throw new IllegalStateException("Multipackage Inconsistency: session " + + childSession.sessionId + " and session " + sessionId + + " have inconsistent staged settings"); + } + if (params.getEnableRollback() != childSession.params.getEnableRollback()) { + throw new IllegalStateException("Multipackage Inconsistency: session " + + childSession.sessionId + " and session " + sessionId + + " have inconsistent rollback settings"); + } try { acquireTransactionLock(); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 0d1c00dfe035..9c8b972985eb 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -248,6 +248,8 @@ import android.os.Debug; import android.os.Environment; import android.os.FileUtils; import android.os.Handler; +import android.os.HandlerExecutor; +import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; @@ -418,7 +420,9 @@ import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; @@ -923,6 +927,7 @@ public class PackageManagerService extends IPackageManager.Stub private final Object mLock; private final Installer mInstaller; private final Object mInstallLock; + private final Executor mBackgroundExecutor; // ----- producers ----- private final Singleton<ComponentResolver> mComponentResolverProducer; @@ -944,6 +949,7 @@ public class PackageManagerService extends IPackageManager.Stub Injector(Context context, Object lock, Installer installer, Object installLock, PackageAbiHelper abiHelper, + Executor backgroundExecutor, Producer<ComponentResolver> componentResolverProducer, Producer<PermissionManagerServiceInternal> permissionManagerProducer, Producer<UserManagerService> userManagerProducer, @@ -965,6 +971,7 @@ public class PackageManagerService extends IPackageManager.Stub mInstaller = installer; mAbiHelper = abiHelper; mInstallLock = installLock; + mBackgroundExecutor = backgroundExecutor; mComponentResolverProducer = new Singleton<>(componentResolverProducer); mPermissionManagerProducer = new Singleton<>(permissionManagerProducer); mUserManagerProducer = new Singleton<>(userManagerProducer); @@ -1078,6 +1085,10 @@ public class PackageManagerService extends IPackageManager.Stub public PlatformCompat getCompatibility() { return mPlatformCompatProducer.get(this, mPackageManager); } + + public Executor getBackgroundExecutor() { + return mBackgroundExecutor; + } } @VisibleForTesting(visibility = Visibility.PRIVATE) @@ -2580,17 +2591,21 @@ public class PackageManagerService extends IPackageManager.Stub t.traceBegin("create package manager"); final Object lock = new Object(); final Object installLock = new Object(); + HandlerThread backgroundThread = new HandlerThread("PackageManagerBg"); + backgroundThread.start(); + Handler backgroundHandler = new Handler(backgroundThread.getLooper()); Injector injector = new Injector( context, lock, installer, installLock, new PackageAbiHelperImpl(), + new HandlerExecutor(backgroundHandler), (i, pm) -> new ComponentResolver(i.getUserManagerService(), pm.mPmInternal, lock), (i, pm) -> - PermissionManagerService.create(context, lock), + PermissionManagerService.create(context, lock), (i, pm) -> - new UserManagerService(context, pm, - new UserDataPreparer(installer, installLock, context, onlyCore), - lock), + new UserManagerService(context, pm, + new UserDataPreparer(installer, installLock, context, onlyCore), + lock), (i, pm) -> new Settings(Environment.getDataDirectory(), i.getPermissionManagerServiceInternal().getPermissionSettings(), @@ -3481,6 +3496,7 @@ public class PackageManagerService extends IPackageManager.Stub return; } int count = 0; + final Installer.Batch batch = new Installer.Batch(); for (String pkgName : deferPackages) { AndroidPackage pkg = null; synchronized (mLock) { @@ -3490,13 +3506,14 @@ public class PackageManagerService extends IPackageManager.Stub } } if (pkg != null) { - synchronized (mInstallLock) { - prepareAppDataAndMigrateLIF(pkg, UserHandle.USER_SYSTEM, storageFlags, - true /* maybeMigrateAppData */); - } + prepareAppDataAndMigrate(batch, pkg, UserHandle.USER_SYSTEM, storageFlags, + true /* maybeMigrateAppData */); count++; } } + synchronized (mInstallLock) { + executeBatchLI(batch); + } traceLog.traceEnd(); Slog.i(TAG, "Deferred reconcileAppsData finished " + count + " packages"); }, "prepareAppData"); @@ -7819,7 +7836,7 @@ public class PackageManagerService extends IPackageManager.Stub // low 'int'-sized word: relative priority among 'always' results. private long getDomainVerificationStatusLPr(PackageSetting ps, int userId) { long result = ps.getDomainVerificationStatusForUser(userId); - // if none available, get the master status + // if none available, get the status if (result >> 32 == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) { if (ps.getIntentFilterVerificationInfo() != null) { result = ((long)ps.getIntentFilterVerificationInfo().getStatus()) << 32; @@ -17279,7 +17296,7 @@ public class PackageManagerService extends IPackageManager.Stub if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile); - // Sanity check + // Validity check if (instantApp && onExternal) { Slog.i(TAG, "Incompatible ephemeral install; external=" + onExternal); throw new PrepareFailure(PackageManager.INSTALL_FAILED_SESSION_INVALID); @@ -17423,7 +17440,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - // Quick sanity check that we're signed correctly if updating; + // Quick validity check that we're signed correctly if updating; // we'll check this again later when scanning, but we want to // bail early here before tripping over redefined permissions. final KeySetManagerService ksms = mSettings.mKeySetManagerService; @@ -17591,9 +17608,6 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mLock) { pkgSetting = mSettings.getPackageLPr(pkgName); } - String abiOverride = - (pkgSetting == null || TextUtils.isEmpty(pkgSetting.cpuAbiOverrideString) - ? args.abiOverride : pkgSetting.cpuAbiOverrideString); boolean isUpdatedSystemAppFromExistingSetting = pkgSetting != null && pkgSetting.getPkgState().isUpdatedSystemApp(); AndroidPackage oldPackage = mPackages.get(pkgName); @@ -17601,7 +17615,7 @@ public class PackageManagerService extends IPackageManager.Stub final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths> derivedAbi = mInjector.getAbiHelper().derivePackageAbi(parsedPackage, isUpdatedSystemAppFromExistingSetting || isUpdatedSystemAppInferred, - abiOverride); + args.abiOverride); derivedAbi.first.applyTo(parsedPackage); derivedAbi.second.applyTo(parsedPackage); } catch (PackageManagerException pme) { @@ -21561,7 +21575,7 @@ public class PackageManagerService extends IPackageManager.Stub // had been set as a preferred activity. We try to clean this up // the next time we encounter that preferred activity, but it is // possible for the user flow to never be able to return to that - // situation so here we do a sanity check to make sure we haven't + // situation so here we do a validity check to make sure we haven't // left any junk around. ArrayList<PreferredActivity> removed = new ArrayList<>(); for (int i=0; i<mSettings.mPreferredActivities.size(); i++) { @@ -22746,6 +22760,14 @@ public class PackageManagerService extends IPackageManager.Stub } } + private void executeBatchLI(@NonNull Installer.Batch batch) { + try { + batch.execute(mInstaller); + } catch (InstallerException e) { + Slog.w(TAG, "Failed to execute pending operations", e); + } + } + /** * Examine all apps present on given mounted volume, and destroy apps that * aren't expected, either due to uninstallation or reinstallation on @@ -22885,6 +22907,8 @@ public class PackageManagerService extends IPackageManager.Stub // Ensure that data directories are ready to roll for all packages // installed for this volume and user + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "prepareAppDataAndMigrate"); + Installer.Batch batch = new Installer.Batch(); final List<PackageSetting> packages; synchronized (mLock) { packages = mSettings.getVolumePackagesLPr(volumeUuid); @@ -22905,10 +22929,12 @@ public class PackageManagerService extends IPackageManager.Stub } if (ps.getInstalled(userId)) { - prepareAppDataAndMigrateLIF(ps.pkg, userId, flags, migrateAppData); + prepareAppDataAndMigrate(batch, ps.pkg, userId, flags, migrateAppData); preparedCount++; } } + executeBatchLI(batch); + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); Slog.v(TAG, "reconcileAppsData finished " + preparedCount + " packages"); return result; @@ -22933,6 +22959,7 @@ public class PackageManagerService extends IPackageManager.Stub mSettings.writeKernelMappingLPr(ps); } + Installer.Batch batch = new Installer.Batch(); UserManagerInternal umInternal = mInjector.getUserManagerInternal(); StorageManagerInternal smInternal = mInjector.getStorageManagerInternal(); for (UserInfo user : mUserManager.getUsers(false /*excludeDying*/)) { @@ -22947,16 +22974,20 @@ public class PackageManagerService extends IPackageManager.Stub if (ps.getInstalled(user.id)) { // TODO: when user data is locked, mark that we're still dirty - prepareAppDataLIF(pkg, user.id, flags); - - if (umInternal.isUserUnlockingOrUnlocked(user.id)) { - // Prepare app data on external storage; currently this is used to - // setup any OBB dirs that were created by the installer correctly. - int uid = UserHandle.getUid(user.id, UserHandle.getAppId(pkg.getUid())); - smInternal.prepareAppDataAfterInstall(pkg.getPackageName(), uid); - } + prepareAppData(batch, pkg, user.id, flags).thenRun(() -> { + // Note: this code block is executed with the Installer lock + // already held, since it's invoked as a side-effect of + // executeBatchLI() + if (umInternal.isUserUnlockingOrUnlocked(user.id)) { + // Prepare app data on external storage; currently this is used to + // setup any OBB dirs that were created by the installer correctly. + int uid = UserHandle.getUid(user.id, UserHandle.getAppId(pkg.getUid())); + smInternal.prepareAppDataAfterInstall(pkg.getPackageName(), uid); + } + }); } } + executeBatchLI(batch); } /** @@ -22967,26 +22998,33 @@ public class PackageManagerService extends IPackageManager.Stub * will try recovering system apps by wiping data; third-party app data is * left intact. */ - private void prepareAppDataLIF(AndroidPackage pkg, int userId, int flags) { + private @NonNull CompletableFuture<?> prepareAppData(@NonNull Installer.Batch batch, + @Nullable AndroidPackage pkg, int userId, int flags) { if (pkg == null) { Slog.wtf(TAG, "Package was null!", new Throwable()); - return; + return CompletableFuture.completedFuture(null); } - prepareAppDataLeafLIF(pkg, userId, flags); + return prepareAppDataLeaf(batch, pkg, userId, flags); } - private void prepareAppDataAndMigrateLIF(AndroidPackage pkg, int userId, int flags, - boolean maybeMigrateAppData) { - prepareAppDataLIF(pkg, userId, flags); - - if (maybeMigrateAppData && maybeMigrateAppDataLIF(pkg, userId)) { - // We may have just shuffled around app data directories, so - // prepare them one more time - prepareAppDataLIF(pkg, userId, flags); - } + private @NonNull CompletableFuture<?> prepareAppDataAndMigrate(@NonNull Installer.Batch batch, + @NonNull AndroidPackage pkg, int userId, int flags, boolean maybeMigrateAppData) { + return prepareAppData(batch, pkg, userId, flags).thenRun(() -> { + // Note: this code block is executed with the Installer lock + // already held, since it's invoked as a side-effect of + // executeBatchLI() + if (maybeMigrateAppData && maybeMigrateAppDataLIF(pkg, userId)) { + // We may have just shuffled around app data directories, so + // prepare them one more time + final Installer.Batch batchInner = new Installer.Batch(); + prepareAppData(batchInner, pkg, userId, flags); + executeBatchLI(batchInner); + } + }); } - private void prepareAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) { + private @NonNull CompletableFuture<?> prepareAppDataLeaf(@NonNull Installer.Batch batch, + @NonNull AndroidPackage pkg, int userId, int flags) { if (DEBUG_APP_DATA) { Slog.v(TAG, "prepareAppData for " + pkg.getPackageName() + " u" + userId + " 0x" + Integer.toHexString(flags)); @@ -23006,57 +23044,67 @@ public class PackageManagerService extends IPackageManager.Stub Preconditions.checkNotNull(pkgSeInfo); final String seInfo = pkgSeInfo + (pkg.getSeInfoUser() != null ? pkg.getSeInfoUser() : ""); - long ceDataInode = -1; - try { - ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags, - appId, seInfo, pkg.getTargetSdkVersion()); - } catch (InstallerException e) { - if (pkg.isSystem()) { - logCriticalInfo(Log.ERROR, "Failed to create app data for " + packageName - + ", but trying to recover: " + e); - destroyAppDataLeafLIF(pkg, userId, flags); - try { - ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags, - appId, seInfo, pkg.getTargetSdkVersion()); - logCriticalInfo(Log.DEBUG, "Recovery succeeded!"); - } catch (InstallerException e2) { - logCriticalInfo(Log.DEBUG, "Recovery failed!"); - } - } else { - Slog.e(TAG, "Failed to create app data for " + packageName + ": " + e); - } - } - // Prepare the application profiles only for upgrades and first boot (so that we don't - // repeat the same operation at each boot). - // We only have to cover the upgrade and first boot here because for app installs we - // prepare the profiles before invoking dexopt (in installPackageLI). - // - // We also have to cover non system users because we do not call the usual install package - // methods for them. - // - // NOTE: in order to speed up first boot time we only create the current profile and do not - // update the content of the reference profile. A system image should already be configured - // with the right profile keys and the profiles for the speed-profile prebuilds should - // already be copied. That's done in #performDexOptUpgrade. - // - // TODO(calin, mathieuc): We should use .dm files for prebuilds profiles instead of - // manually copying them in #performDexOptUpgrade. When we do that we should have a more - // granular check here and only update the existing profiles. - if (mIsUpgrade || mFirstBoot || (userId != UserHandle.USER_SYSTEM)) { - mArtManagerService.prepareAppProfiles(pkg, userId, - /* updateReferenceProfileContent= */ false); - } + final int targetSdkVersion = pkg.getTargetSdkVersion(); + + return batch.createAppData(volumeUuid, packageName, userId, flags, appId, seInfo, + targetSdkVersion).whenComplete((ceDataInode, e) -> { + // Note: this code block is executed with the Installer lock + // already held, since it's invoked as a side-effect of + // executeBatchLI() + if ((e != null) && pkg.isSystem()) { + logCriticalInfo(Log.ERROR, "Failed to create app data for " + packageName + + ", but trying to recover: " + e); + destroyAppDataLeafLIF(pkg, userId, flags); + try { + ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, + flags, appId, seInfo, pkg.getTargetSdkVersion()); + logCriticalInfo(Log.DEBUG, "Recovery succeeded!"); + } catch (InstallerException e2) { + logCriticalInfo(Log.DEBUG, "Recovery failed!"); + } + } else if (e != null) { + Slog.e(TAG, "Failed to create app data for " + packageName + ": " + e); + } - if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && ceDataInode != -1) { - // TODO: mark this structure as dirty so we persist it! - synchronized (mLock) { - if (ps != null) { - ps.setCeDataInode(ceDataInode, userId); - } - } - } + // Prepare the application profiles only for upgrades and + // first boot (so that we don't repeat the same operation at + // each boot). + // + // We only have to cover the upgrade and first boot here + // because for app installs we prepare the profiles before + // invoking dexopt (in installPackageLI). + // + // We also have to cover non system users because we do not + // call the usual install package methods for them. + // + // NOTE: in order to speed up first boot time we only create + // the current profile and do not update the content of the + // reference profile. A system image should already be + // configured with the right profile keys and the profiles + // for the speed-profile prebuilds should already be copied. + // That's done in #performDexOptUpgrade. + // + // TODO(calin, mathieuc): We should use .dm files for + // prebuilds profiles instead of manually copying them in + // #performDexOptUpgrade. When we do that we should have a + // more granular check here and only update the existing + // profiles. + if (mIsUpgrade || mFirstBoot || (userId != UserHandle.USER_SYSTEM)) { + mArtManagerService.prepareAppProfiles(pkg, userId, + /* updateReferenceProfileContent= */ false); + } + + if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && ceDataInode != -1) { + // TODO: mark this structure as dirty so we persist it! + synchronized (mLock) { + if (ps != null) { + ps.setCeDataInode(ceDataInode, userId); + } + } + } - prepareAppDataContentsLeafLIF(pkg, ps, userId, flags); + prepareAppDataContentsLeafLIF(pkg, ps, userId, flags); + }); } private void prepareAppDataContentsLIF(AndroidPackage pkg, @Nullable PackageSetting pkgSetting, diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 7aeec6d68d26..32ec052a1fe0 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -1043,7 +1043,9 @@ class PackageManagerShellCommand extends ShellCommand { + "; isStaged = " + session.isStaged() + "; isReady = " + session.isStagedSessionReady() + "; isApplied = " + session.isStagedSessionApplied() - + "; isFailed = " + session.isStagedSessionFailed() + ";"); + + "; isFailed = " + session.isStagedSessionFailed() + + "; errorMsg = " + session.getStagedSessionErrorMessage() + + ";"); } private Intent parseIntentAndUser() throws URISyntaxException { @@ -3338,7 +3340,7 @@ class PackageManagerShellCommand extends ShellCommand { session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); if (!session.isMultiPackage() && !session.isStaged()) { - // Sanity check that all .dm files match an apk. + // Validity check that all .dm files match an apk. // (The installer does not support standalone .dm files and will not process them.) try { DexMetadataHelper.validateDexPaths(session.getNames()); diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 3e253673ad31..acb149b9ec3d 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -102,6 +102,7 @@ import com.android.internal.util.XmlUtils; import com.android.permission.persistence.RuntimePermissionsPersistence; import com.android.permission.persistence.RuntimePermissionsState; import com.android.server.LocalServices; +import com.android.server.pm.Installer.Batch; import com.android.server.pm.Installer.InstallerException; import com.android.server.pm.parsing.PackageInfoUtils; import com.android.server.pm.parsing.pkg.AndroidPackage; @@ -4148,24 +4149,12 @@ public final class Settings { final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing", Trace.TRACE_TAG_PACKAGE_MANAGER); t.traceBegin("createNewUser-" + userHandle); - String[] volumeUuids; - String[] names; - int[] appIds; - String[] seinfos; - int[] targetSdkVersions; - int packagesCount; + Installer.Batch batch = new Installer.Batch(); final boolean skipPackageWhitelist = userTypeInstallablePackages == null; synchronized (mLock) { - Collection<PackageSetting> packages = mPackages.values(); - packagesCount = packages.size(); - volumeUuids = new String[packagesCount]; - names = new String[packagesCount]; - appIds = new int[packagesCount]; - seinfos = new String[packagesCount]; - targetSdkVersions = new int[packagesCount]; - Iterator<PackageSetting> packagesIterator = packages.iterator(); - for (int i = 0; i < packagesCount; i++) { - PackageSetting ps = packagesIterator.next(); + final int size = mPackages.size(); + for (int i = 0; i < size; i++) { + final PackageSetting ps = mPackages.valueAt(i); if (ps.pkg == null) { continue; } @@ -4187,18 +4176,15 @@ public final class Settings { } // Need to create a data directory for all apps under this user. Accumulate all // required args and call the installer after mPackages lock has been released - volumeUuids[i] = ps.volumeUuid; - names[i] = ps.name; - appIds[i] = ps.appId; - seinfos[i] = AndroidPackageUtils.getSeInfo(ps.pkg, ps); - targetSdkVersions[i] = ps.pkg.getTargetSdkVersion(); + final String seInfo = AndroidPackageUtils.getSeInfo(ps.pkg, ps); + batch.createAppData(ps.volumeUuid, ps.name, userHandle, + StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE, ps.appId, + seInfo, ps.pkg.getTargetSdkVersion()); } } t.traceBegin("createAppData"); - final int flags = StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE; try { - installer.createAppDataBatched(volumeUuids, names, userHandle, flags, appIds, seinfos, - targetSdkVersions); + batch.execute(installer); } catch (InstallerException e) { Slog.w(TAG, "Failed to prepare app data", e); } diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index ac05aabf998f..6d80f08ecbf6 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -591,13 +591,14 @@ public class StagingManager { // If checkpoint is supported, then we only resume sessions if we are in checkpointing // mode. If not, we fail all sessions. if (supportsCheckpoint() && !needsCheckpoint()) { - String errorMsg = "Reverting back to safe state. Marking " + session.sessionId - + " as failed"; - if (!TextUtils.isEmpty(mFailureReason)) { - errorMsg = errorMsg + ": " + mFailureReason; + String revertMsg = "Reverting back to safe state. Marking " + + session.sessionId + " as failed."; + final String reasonForRevert = getReasonForRevert(); + if (!TextUtils.isEmpty(reasonForRevert)) { + revertMsg += " Reason for revert: " + reasonForRevert; } - Slog.d(TAG, errorMsg); - session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_UNKNOWN, errorMsg); + Slog.d(TAG, revertMsg); + session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_UNKNOWN, revertMsg); return; } } catch (RemoteException e) { @@ -702,6 +703,16 @@ public class StagingManager { } } + private String getReasonForRevert() { + if (!TextUtils.isEmpty(mFailureReason)) { + return mFailureReason; + } + if (!TextUtils.isEmpty(mNativeFailureReason)) { + return "Session reverted due to crashing native process: " + mNativeFailureReason; + } + return ""; + } + private List<String> findAPKsInDir(File stageDir) { List<String> ret = new ArrayList<>(); if (stageDir != null && stageDir.exists()) { diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index f66b4ee5a1a7..d137fd05f793 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -499,20 +499,23 @@ public class UserManagerService extends IUserManager.Stub { states = new SparseIntArray(); invalidateIsUserUnlockedCache(); } - public int get(int userId) { + public int get(@UserIdInt int userId) { return states.get(userId); } - public int get(int userId, int fallback) { + public int get(@UserIdInt int userId, int fallback) { return states.indexOfKey(userId) >= 0 ? states.get(userId) : fallback; } - public void put(int userId, int state) { + public void put(@UserIdInt int userId, int state) { states.put(userId, state); invalidateIsUserUnlockedCache(); } - public void delete(int userId) { + public void delete(@UserIdInt int userId) { states.delete(userId); invalidateIsUserUnlockedCache(); } + public boolean has(@UserIdInt int userId) { + return states.get(userId, UserHandle.USER_NULL) != UserHandle.USER_NULL; + } @Override public String toString() { return states.toString(); @@ -3561,6 +3564,13 @@ public class UserManagerService extends IUserManager.Stub { if (preCreatedUserData == null) { return null; } + synchronized (mUserStates) { + if (mUserStates.has(preCreatedUserData.info.id)) { + Slog.w(LOG_TAG, "Cannot reuse pre-created user " + + preCreatedUserData.info.id + " because it didn't stop yet"); + return null; + } + } final UserInfo preCreatedUser = preCreatedUserData.info; final int newFlags = preCreatedUser.flags | flags; if (!checkUserTypeConsistency(newFlags)) { @@ -5225,6 +5235,7 @@ public class UserManagerService extends IUserManager.Stub { return userData == null ? null : userData.info; } + @Override public @NonNull UserInfo[] getUserInfos() { synchronized (mUsersLock) { int userSize = mUsers.size(); 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 3d1570476b48..1be74154b53a 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -2464,7 +2464,28 @@ public class PermissionManagerService extends IPermissionManager.Stub { return null; } final PermissionsState permissionsState = ps.getPermissionsState(); - return permissionsState.getPermissions(userId); + if (!ps.getInstantApp(userId)) { + return permissionsState.getPermissions(userId); + } else { + // Install permission state is shared among all users, but instant app state is + // per-user, so we can only filter it here unless we make install permission state + // per-user as well. + final Set<String> instantPermissions = new ArraySet<>(permissionsState.getPermissions( + userId)); + instantPermissions.removeIf(permissionName -> { + BasePermission permission = mSettings.getPermission(permissionName); + if (permission == null) { + return true; + } + if (!permission.isInstant()) { + EventLog.writeEvent(0x534e4554, "140256621", UserHandle.getUid(userId, + ps.getAppId()), permissionName); + return true; + } + return false; + }); + return instantPermissions; + } } @Nullable @@ -4427,7 +4448,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { * @param checkShell whether to prevent shell from access if there's a debugging restriction * @param message the message to log on security exception */ - private void enforceCrossUserPermission(int callingUid, int userId, + private void enforceCrossUserPermission(int callingUid, @UserIdInt int userId, boolean requireFullPermission, boolean checkShell, boolean requirePermissionWhenSameUser, String message) { if (userId < 0) { @@ -4444,7 +4465,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { return; } String errorMessage = buildInvalidCrossUserPermissionMessage( - message, requireFullPermission); + callingUid, userId, message, requireFullPermission); Slog.w(TAG, errorMessage); throw new SecurityException(errorMessage); } @@ -4463,7 +4484,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { * @param checkShell whether to prevent shell from access if there's a debugging restriction * @param message the message to log on security exception */ - private void enforceCrossUserOrProfilePermission(int callingUid, int userId, + private void enforceCrossUserOrProfilePermission(int callingUid, @UserIdInt int userId, boolean requireFullPermission, boolean checkShell, String message) { if (userId < 0) { @@ -4489,7 +4510,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { return; } String errorMessage = buildInvalidCrossUserOrProfilePermissionMessage( - message, requireFullPermission, isSameProfileGroup); + callingUid, userId, message, requireFullPermission, isSameProfileGroup); Slog.w(TAG, errorMessage); throw new SecurityException(errorMessage); } @@ -4524,44 +4545,48 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } - private static String buildInvalidCrossUserPermissionMessage( - String message, boolean requireFullPermission) { + private static String buildInvalidCrossUserPermissionMessage(int callingUid, + @UserIdInt int userId, String message, boolean requireFullPermission) { StringBuilder builder = new StringBuilder(); if (message != null) { builder.append(message); builder.append(": "); } - builder.append("Requires "); + builder.append("UID "); + builder.append(callingUid); + builder.append(" requires "); builder.append(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); - if (requireFullPermission) { - builder.append("."); - return builder.toString(); + if (!requireFullPermission) { + builder.append(" or "); + builder.append(android.Manifest.permission.INTERACT_ACROSS_USERS); } - builder.append(" or "); - builder.append(android.Manifest.permission.INTERACT_ACROSS_USERS); + builder.append(" to access user "); + builder.append(userId); builder.append("."); return builder.toString(); } - private static String buildInvalidCrossUserOrProfilePermissionMessage( - String message, boolean requireFullPermission, boolean isSameProfileGroup) { + private static String buildInvalidCrossUserOrProfilePermissionMessage(int callingUid, + @UserIdInt int userId, String message, boolean requireFullPermission, + boolean isSameProfileGroup) { StringBuilder builder = new StringBuilder(); if (message != null) { builder.append(message); builder.append(": "); } - builder.append("Requires "); + builder.append("UID "); + builder.append(callingUid); + builder.append(" requires "); builder.append(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); - if (requireFullPermission) { - builder.append("."); - return builder.toString(); - } - builder.append(" or "); - builder.append(android.Manifest.permission.INTERACT_ACROSS_USERS); - if (isSameProfileGroup) { + if (!requireFullPermission) { builder.append(" or "); - builder.append(android.Manifest.permission.INTERACT_ACROSS_PROFILES); + builder.append(android.Manifest.permission.INTERACT_ACROSS_USERS); + if (isSameProfileGroup) { + builder.append(" or "); + builder.append(android.Manifest.permission.INTERACT_ACROSS_PROFILES); + } } + builder.append(" to access user "); builder.append("."); return builder.toString(); } diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 6adff0d32d88..0c85387be695 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -1156,7 +1156,7 @@ public class TrustManagerService extends SystemService { } private void enforceListenerPermission() { - mContext.enforceCallingPermission(Manifest.permission.TRUST_LISTENER, + mContext.enforceCallingOrSelfPermission(Manifest.permission.TRUST_LISTENER, "register trust listener"); } diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java b/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java index 2b0fe8a2602b..2fc17fe65775 100644 --- a/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java +++ b/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java @@ -68,6 +68,11 @@ public final class ClientProfile { private Set<Integer> mUsingFrontendIds = new HashSet<>(); /** + * List of the client ids that share frontend with the current client. + */ + private Set<Integer> mShareFeClientIds = new HashSet<>(); + + /** * List of the Lnb ids that are used by the current client. */ private Set<Integer> mUsingLnbIds = new HashSet<>(); @@ -113,11 +118,7 @@ public final class ClientProfile { } public int getPriority() { - return mPriority; - } - - public int getNiceValue() { - return mNiceValue; + return mPriority - mNiceValue; } public void setGroupId(int groupId) { @@ -141,17 +142,38 @@ public final class ClientProfile { mUsingFrontendIds.add(frontendId); } + /** + * Update the set of client that share frontend with the current client. + * + * @param clientId the client to share the fe with the current client. + */ + public void shareFrontend(int clientId) { + mShareFeClientIds.add(clientId); + } + + /** + * Remove the given client id from the share frontend client id set. + * + * @param clientId the client to stop sharing the fe with the current client. + */ + public void stopSharingFrontend(int clientId) { + mShareFeClientIds.remove(clientId); + } + public Set<Integer> getInUseFrontendIds() { return mUsingFrontendIds; } + public Set<Integer> getShareFeClientIds() { + return mShareFeClientIds; + } + /** * Called when the client released a frontend. - * - * @param frontendId being released. */ - public void releaseFrontend(int frontendId) { - mUsingFrontendIds.remove(frontendId); + public void releaseFrontend() { + mUsingFrontendIds.clear(); + mShareFeClientIds.clear(); } /** @@ -201,6 +223,7 @@ public final class ClientProfile { */ public void reclaimAllResources() { mUsingFrontendIds.clear(); + mShareFeClientIds.clear(); mUsingLnbIds.clear(); mUsingCasSystemId = INVALID_RESOURCE_ID; } diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java index 7cb59dcbfb9b..fb2347e8e133 100644 --- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java +++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java @@ -210,19 +210,36 @@ public class TunerResourceManagerService extends SystemService implements IBinde } synchronized (mLock) { if (!checkClientExists(request.getClientId())) { - throw new RemoteException("Request frontend from unregistered client:" + throw new RemoteException("Request frontend from unregistered client: " + request.getClientId()); } + // If the request client is holding or sharing a frontend, throw an exception. + if (!getClientProfile(request.getClientId()).getInUseFrontendIds().isEmpty()) { + throw new RemoteException("Release frontend before requesting another one. " + + "Client id: " + request.getClientId()); + } return requestFrontendInternal(request, frontendHandle); } } @Override - public void shareFrontend(int selfClientId, int targetClientId) { + public void shareFrontend(int selfClientId, int targetClientId) throws RemoteException { enforceTunerAccessPermission("shareFrontend"); enforceTrmAccessPermission("shareFrontend"); - if (DEBUG) { - Slog.d(TAG, "shareFrontend from " + selfClientId + " with " + targetClientId); + synchronized (mLock) { + if (!checkClientExists(selfClientId)) { + throw new RemoteException("Share frontend request from an unregistered client:" + + selfClientId); + } + if (!checkClientExists(targetClientId)) { + throw new RemoteException("Request to share frontend with an unregistered " + + "client:" + targetClientId); + } + if (getClientProfile(targetClientId).getInUseFrontendIds().isEmpty()) { + throw new RemoteException("Request to share frontend with a client that has no " + + "frontend resources. Target client id:" + targetClientId); + } + shareFrontendInternal(selfClientId, targetClientId); } } @@ -315,7 +332,7 @@ public class TunerResourceManagerService extends SystemService implements IBinde throw new RemoteException( "Client is not the current owner of the releasing fe."); } - releaseFrontendInternal(fe); + releaseFrontendInternal(fe, clientId); } } @@ -649,6 +666,17 @@ public class TunerResourceManagerService extends SystemService implements IBinde } @VisibleForTesting + protected void shareFrontendInternal(int selfClientId, int targetClientId) { + if (DEBUG) { + Slog.d(TAG, "shareFrontend from " + selfClientId + " with " + targetClientId); + } + for (int feId : getClientProfile(targetClientId).getInUseFrontendIds()) { + getClientProfile(selfClientId).useFrontend(feId); + } + getClientProfile(targetClientId).shareFrontend(selfClientId); + } + + @VisibleForTesting protected boolean requestLnbInternal(TunerLnbRequest request, int[] lnbHandle) { if (DEBUG) { Slog.d(TAG, "requestLnb(request=" + request + ")"); @@ -777,11 +805,17 @@ public class TunerResourceManagerService extends SystemService implements IBinde } @VisibleForTesting - protected void releaseFrontendInternal(FrontendResource fe) { + protected void releaseFrontendInternal(FrontendResource fe, int clientId) { if (DEBUG) { - Slog.d(TAG, "releaseFrontend(id=" + fe.getId() + ")"); + Slog.d(TAG, "releaseFrontend(id=" + fe.getId() + ", clientId=" + clientId + " )"); + } + if (clientId == fe.getOwnerClientId()) { + ClientProfile ownerClient = getClientProfile(fe.getOwnerClientId()); + for (int shareOwnerId : ownerClient.getShareFeClientIds()) { + clearFrontendAndClientMapping(getClientProfile(shareOwnerId)); + } } - updateFrontendClientMappingOnRelease(fe); + clearFrontendAndClientMapping(getClientProfile(clientId)); } @VisibleForTesting @@ -882,8 +916,21 @@ public class TunerResourceManagerService extends SystemService implements IBinde Slog.e(TAG, "Failed to reclaim resources on client " + reclaimingClientId, e); return false; } + + // Reclaim all the resources of the share owners of the frontend that is used by the current + // resource reclaimed client. ClientProfile profile = getClientProfile(reclaimingClientId); - reclaimingResourcesFromClient(profile); + Set<Integer> shareFeClientIds = profile.getShareFeClientIds(); + for (int clientId : shareFeClientIds) { + try { + mListeners.get(clientId).getListener().onReclaimResources(); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to reclaim resources on client " + clientId, e); + return false; + } + clearAllResourcesAndClientMapping(getClientProfile(clientId)); + } + clearAllResourcesAndClientMapping(profile); return true; } @@ -929,16 +976,6 @@ public class TunerResourceManagerService extends SystemService implements IBinde } } - private void updateFrontendClientMappingOnRelease(@NonNull FrontendResource releasingFrontend) { - ClientProfile ownerProfile = getClientProfile(releasingFrontend.getOwnerClientId()); - releasingFrontend.removeOwner(); - ownerProfile.releaseFrontend(releasingFrontend.getId()); - for (int exclusiveGroupMember : releasingFrontend.getExclusiveGroupMemberFeIds()) { - getFrontendResource(exclusiveGroupMember).removeOwner(); - ownerProfile.releaseFrontend(exclusiveGroupMember); - } - } - private void updateLnbClientMappingOnNewGrant(int grantingId, int ownerClientId) { LnbResource grantingLnb = getLnbResource(grantingId); ClientProfile ownerProfile = getClientProfile(ownerClientId); @@ -967,10 +1004,10 @@ public class TunerResourceManagerService extends SystemService implements IBinde } /** - * Get the owner client's priority from the resource id. + * Get the owner client's priority. * * @param clientId the owner client id. - * @return the priority of the owner client of the resource. + * @return the priority of the owner client. */ private int getOwnerClientPriority(int clientId) { return getClientProfile(clientId).getPriority(); @@ -1011,7 +1048,11 @@ public class TunerResourceManagerService extends SystemService implements IBinde return; } if (fe.isInUse()) { - releaseFrontendInternal(fe); + ClientProfile ownerClient = getClientProfile(fe.getOwnerClientId()); + for (int shareOwnerId : ownerClient.getShareFeClientIds()) { + clearFrontendAndClientMapping(getClientProfile(shareOwnerId)); + } + clearFrontendAndClientMapping(ownerClient); } for (int excGroupmemberFeId : fe.getExclusiveGroupMemberFeIds()) { getFrontendResource(excGroupmemberFeId) @@ -1093,21 +1134,37 @@ public class TunerResourceManagerService extends SystemService implements IBinde } private void removeClientProfile(int clientId) { - reclaimingResourcesFromClient(getClientProfile(clientId)); + for (int shareOwnerId : getClientProfile(clientId).getShareFeClientIds()) { + clearFrontendAndClientMapping(getClientProfile(shareOwnerId)); + } + clearAllResourcesAndClientMapping(getClientProfile(clientId)); mClientProfiles.remove(clientId); mListeners.remove(clientId); } - private void reclaimingResourcesFromClient(ClientProfile profile) { + private void clearFrontendAndClientMapping(ClientProfile profile) { for (Integer feId : profile.getInUseFrontendIds()) { - getFrontendResource(feId).removeOwner(); + FrontendResource fe = getFrontendResource(feId); + if (fe.getOwnerClientId() == profile.getId()) { + fe.removeOwner(); + continue; + } + getClientProfile(fe.getOwnerClientId()).stopSharingFrontend(profile.getId()); } + profile.releaseFrontend(); + } + + private void clearAllResourcesAndClientMapping(ClientProfile profile) { + // Clear Lnb for (Integer lnbId : profile.getInUseLnbIds()) { getLnbResource(lnbId).removeOwner(); } + // Clear Cas if (profile.getInUseCasSystemId() != ClientProfile.INVALID_RESOURCE_ID) { getCasResource(profile.getInUseCasSystemId()).removeOwner(profile.getId()); } + // Clear Frontend + clearFrontendAndClientMapping(profile); profile.reclaimAllResources(); } diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index 7565d8f9647c..6e9526afa962 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -542,7 +542,7 @@ class ActivityMetricsLogger { + " processSwitch=" + processSwitch + " info=" + info); } - if (launchedActivity.mDrawn) { + if (launchedActivity.isReportedDrawn()) { // Launched activity is already visible. We cannot measure windows drawn delay. abort(info, "launched activity already visible"); return; @@ -681,7 +681,7 @@ class ActivityMetricsLogger { /** @return {@code true} if the given task has an activity will be drawn. */ private static boolean hasActivityToBeDrawn(Task t) { - return t.forAllActivities((r) -> r.mVisibleRequested && !r.mDrawn && !r.finishing); + return t.forAllActivities(r -> r.mVisibleRequested && !r.isReportedDrawn() && !r.finishing); } private void checkVisibility(Task t, ActivityRecord r) { diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index e4f28546a5fd..64fa6ca590d2 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -499,7 +499,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // and reporting to the client that it is hidden. private boolean mSetToSleep; // have we told the activity to sleep? boolean nowVisible; // is this activity's window visible? - boolean mDrawn; // is this activity's window drawn? boolean mClientVisibilityDeferred;// was the visibility change message to client deferred? boolean idle; // has the activity gone idle? boolean hasBeenLaunched;// has this activity ever been launched? @@ -564,8 +563,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private boolean mClientVisible; boolean firstWindowDrawn; - // Last drawn state we reported to the app token. - private boolean reportedDrawn; + /** Whether the visible window(s) of this activity is drawn. */ + private boolean mReportedDrawn; private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults = new WindowState.UpdateReportedVisibilityResults(); @@ -927,7 +926,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A pw.println(prefix + "mVisibleRequested=" + mVisibleRequested + " mVisible=" + mVisible + " mClientVisible=" + mClientVisible + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "") - + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible); + + " reportedDrawn=" + mReportedDrawn + " reportedVisible=" + reportedVisible); if (paused) { pw.print(prefix); pw.print("paused="); pw.println(paused); } @@ -1213,14 +1212,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return task; } - /** - * Sets the Task on this activity for the purposes of re-use during launch where we will - * re-use another activity instead of this one for the launch. - */ - void setTaskForReuse(Task task) { - this.task = task; - } - Task getStack() { return task != null ? task.getRootTask() : null; } @@ -1591,7 +1582,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A keysPaused = false; inHistory = false; nowVisible = false; - mDrawn = false; mClientVisible = true; idle = false; hasBeenLaunched = false; @@ -5404,11 +5394,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } /** Called when the windows associated app window container are drawn. */ - void onWindowsDrawn(boolean drawn, long timestampNs) { - mDrawn = drawn; - if (!drawn) { - return; - } + private void onWindowsDrawn(long timestampNs) { final TransitionInfoSnapshot info = mStackSupervisor .getActivityMetricsLogger().notifyWindowsDrawn(this, timestampNs); final boolean validInfo = info != null; @@ -5514,7 +5500,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (!nowGone) { // If the app is not yet gone, then it can only become visible/drawn. if (!nowDrawn) { - nowDrawn = reportedDrawn; + nowDrawn = mReportedDrawn; } if (!nowVisible) { nowVisible = reportedVisible; @@ -5522,9 +5508,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting=" + numInteresting + " visible=" + numVisible); - if (nowDrawn != reportedDrawn) { - onWindowsDrawn(nowDrawn, SystemClock.elapsedRealtimeNanos()); - reportedDrawn = nowDrawn; + if (nowDrawn != mReportedDrawn) { + if (nowDrawn) { + onWindowsDrawn(SystemClock.elapsedRealtimeNanos()); + } + mReportedDrawn = nowDrawn; } if (nowVisible != reportedVisible) { if (DEBUG_VISIBILITY) Slog.v(TAG, @@ -5538,6 +5526,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } } + boolean isReportedDrawn() { + return mReportedDrawn; + } + boolean isClientVisible() { return mClientVisible; } @@ -7677,7 +7669,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A proto.write(VISIBLE_REQUESTED, mVisibleRequested); proto.write(CLIENT_VISIBLE, mClientVisible); proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient); - proto.write(REPORTED_DRAWN, reportedDrawn); + proto.write(REPORTED_DRAWN, mReportedDrawn); proto.write(REPORTED_VISIBLE, reportedVisible); proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows); proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows); diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 15e88fc44746..f6158383d28a 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1766,8 +1766,8 @@ class ActivityStarter { } else if (mInTask != null) { return mInTask; } else { - final Task stack = getLaunchStack(mStartActivity, mLaunchFlags, - null /* task */, mOptions); + final Task stack = getLaunchStack(mStartActivity, mLaunchFlags, null /* task */, + mOptions); final ActivityRecord top = stack.getTopNonFinishingActivity(); if (top != null) { return top.getTask(); @@ -1870,13 +1870,7 @@ class ActivityStarter { return START_SUCCESS; } - boolean clearTaskForReuse = false; if (reusedTask != null) { - if (mStartActivity.getTask() == null) { - mStartActivity.setTaskForReuse(reusedTask); - clearTaskForReuse = true; - } - if (targetTask.intent == null) { // This task was started because of movement of the activity based on // affinity... @@ -1923,13 +1917,6 @@ class ActivityStarter { complyActivityFlags(targetTask, reusedTask != null ? reusedTask.getTopNonFinishingActivity() : null, intentGrants); - if (clearTaskForReuse) { - // Clear task for re-use so later code to methods - // {@link #setTaskFromReuseOrCreateNewTask}, {@link #setTaskFromSourceRecord}, or - // {@link #setTaskFromInTask} can parent it to the task. - mStartActivity.setTaskForReuse(null); - } - if (mAddingToTask) { return START_SUCCESS; } @@ -2515,8 +2502,8 @@ class ActivityStarter { intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask()); } - final Task launchStack = - getLaunchStack(mStartActivity, mLaunchFlags, intentTask, mOptions); + final Task launchStack = getLaunchStack(mStartActivity, mLaunchFlags, intentTask, + mOptions); if (launchStack == null || launchStack == mTargetStack) { // Do not set mMovedToFront to true below for split-screen-top stack, or // START_TASK_TO_FRONT will be returned and trigger unexpected animations when a diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index affbafa095cc..2e879810c085 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -117,7 +117,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.H.REPORT_FOCUS_CHANGE; import static com.android.server.wm.WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE; -import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS; import static com.android.server.wm.WindowManagerService.H.UPDATE_MULTI_WINDOW_STACKS; import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT; import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD; @@ -469,12 +468,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp WindowState mLastFocus = null; /** - * Windows that have lost input focus and are waiting for the new focus window to be displayed - * before they are told about this. - */ - ArrayList<WindowState> mLosingFocus = new ArrayList<>(); - - /** * The foreground app of this display. Windows below this app cannot be the focused window. If * the user taps on the area outside of the task of the focused app, we will notify AM about the * new task the user wants to interact with. @@ -899,10 +892,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } } - if (!mLosingFocus.isEmpty() && w.isFocused() && w.isDisplayedLw()) { - mWmService.mH.obtainMessage(REPORT_LOSING_FOCUS, this).sendToTarget(); - } - w.updateResizingWindowIfNeeded(); }; @@ -2924,21 +2913,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (mLastFocus != mCurrentFocus) { pw.print(" mLastFocus="); pw.println(mLastFocus); } - if (mLosingFocus.size() > 0) { - pw.println(); - pw.println(" Windows losing focus:"); - for (int i = mLosingFocus.size() - 1; i >= 0; i--) { - final WindowState w = mLosingFocus.get(i); - pw.print(" Losing #"); pw.print(i); pw.print(' '); - pw.print(w); - if (dumpAll) { - pw.println(":"); - w.dump(pw, " ", true); - } else { - pw.println(); - } - } - } pw.print(" mFocusedApp="); pw.println(mFocusedApp); if (mLastStatusBarVisibility != 0) { pw.print(" mLastStatusBarVisibility=0x"); @@ -3157,7 +3131,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mCurrentFocus, newFocus, getDisplayId(), Debug.getCallers(4)); final WindowState oldFocus = mCurrentFocus; mCurrentFocus = newFocus; - mLosingFocus.remove(newFocus); if (newFocus != null) { mWinAddedSinceNullFocus.clear(); diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index fe2d08f6a4c2..aeaffd98f820 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -2816,7 +2816,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> * @param launchParams The resolved launch params to use. * @param realCallingPid The pid from {@link ActivityStarter#setRealCallingPid} * @param realCallingUid The uid from {@link ActivityStarter#setRealCallingUid} - * * @return The stack to use for the launch or INVALID_STACK_ID. */ Task getLaunchStack(@Nullable ActivityRecord r, @@ -2965,10 +2964,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // If {@code r} is already in target display area and its task is the same as the candidate // task, the intention should be getting a launch stack for the reusable activity, so we can // use the existing stack. - if (candidateTask != null && (r.getTask() == null || r.getTask() == candidateTask)) { - // TODO(b/153920825): Fix incorrect evaluation of attached state - final TaskDisplayArea attachedTaskDisplayArea = r.getTask() != null - ? r.getTask().getDisplayArea() : r.getDisplayArea(); + if (candidateTask != null) { + final TaskDisplayArea attachedTaskDisplayArea = candidateTask.getDisplayArea(); if (attachedTaskDisplayArea == null || attachedTaskDisplayArea == taskDisplayArea) { return candidateTask.getRootTask(); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 7624d4c1ea36..cd222a97f4d9 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -4740,7 +4740,6 @@ public class WindowManagerService extends IWindowManager.Stub final class H extends android.os.Handler { public static final int REPORT_FOCUS_CHANGE = 2; - public static final int REPORT_LOSING_FOCUS = 3; public static final int WINDOW_FREEZE_TIMEOUT = 11; public static final int PERSIST_ANIMATION_SCALE = 14; @@ -4815,11 +4814,6 @@ public class WindowManagerService extends IWindowManager.Stub ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Focus moving from %s" + " to %s displayId=%d", lastFocus, newFocus, displayContent.getDisplayId()); - if (newFocus != null && lastFocus != null && !newFocus.isDisplayedLw()) { - ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Delaying loss of focus..."); - displayContent.mLosingFocus.add(lastFocus); - lastFocus = null; - } } // First notify the accessibility manager for the change so it has @@ -4842,24 +4836,6 @@ public class WindowManagerService extends IWindowManager.Stub break; } - case REPORT_LOSING_FOCUS: { - final DisplayContent displayContent = (DisplayContent) msg.obj; - ArrayList<WindowState> losers; - - synchronized (mGlobalLock) { - losers = displayContent.mLosingFocus; - displayContent.mLosingFocus = new ArrayList<>(); - } - - final int N = losers.size(); - for (int i = 0; i < N; i++) { - ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Losing delayed focus: %s", - losers.get(i)); - losers.get(i).reportFocusChangedSerialized(false); - } - break; - } - case WINDOW_FREEZE_TIMEOUT: { final DisplayContent displayContent = (DisplayContent) msg.obj; synchronized (mGlobalLock) { diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp index 529fb8838aa1..b3f3a5e1ff72 100644 --- a/services/core/jni/com_android_server_VibratorService.cpp +++ b/services/core/jni/com_android_server_VibratorService.cpp @@ -181,6 +181,24 @@ static jintArray vibratorGetSupportedEffects(JNIEnv* env, jclass /* clazz */, jl return effects; } +static jintArray vibratorGetSupportedPrimitives(JNIEnv* env, jclass /* clazz */, + jlong controllerPtr) { + vibrator::HalController* controller = reinterpret_cast<vibrator::HalController*>(controllerPtr); + if (controller == nullptr) { + ALOGE("vibratorGetSupportedPrimitives failed because controller was not initialized"); + return nullptr; + } + auto result = controller->getSupportedPrimitives(); + if (!result.isOk()) { + return nullptr; + } + std::vector<aidl::CompositePrimitive> supportedPrimitives = result.value(); + jintArray primitives = env->NewIntArray(supportedPrimitives.size()); + env->SetIntArrayRegion(primitives, 0, supportedPrimitives.size(), + reinterpret_cast<jint*>(supportedPrimitives.data())); + return primitives; +} + static jlong vibratorPerformEffect(JNIEnv* env, jclass /* clazz */, jlong controllerPtr, jlong effect, jlong strength, jobject vibration) { vibrator::HalController* controller = reinterpret_cast<vibrator::HalController*>(controllerPtr); @@ -259,6 +277,7 @@ static const JNINativeMethod method_table[] = { "VibratorService$Vibration;)V", (void*)vibratorPerformComposedEffect}, {"vibratorGetSupportedEffects", "(J)[I", (void*)vibratorGetSupportedEffects}, + {"vibratorGetSupportedPrimitives", "(J)[I", (void*)vibratorGetSupportedPrimitives}, {"vibratorSetExternalControl", "(JZ)V", (void*)vibratorSetExternalControl}, {"vibratorGetCapabilities", "(J)J", (void*)vibratorGetCapabilities}, {"vibratorAlwaysOnEnable", "(JJJJ)V", (void*)vibratorAlwaysOnEnable}, diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 2ab629bf725a..6154bef2bda3 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -1579,21 +1579,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { /** * Creates a new {@link CallerIdentity} object to represent the caller's identity. + * The component name should be an active admin for the calling user. */ - private CallerIdentity getCallerIdentity(@NonNull ComponentName componentName) { + private CallerIdentity getCallerIdentity(@NonNull ComponentName adminComponent) { final int callerUid = mInjector.binderGetCallingUid(); final DevicePolicyData policy = getUserData(UserHandle.getUserId(callerUid)); - ActiveAdmin admin = policy.mAdminMap.get(componentName); + ActiveAdmin admin = policy.mAdminMap.get(adminComponent); if (admin == null) { - throw new SecurityException(String.format("No active admin for %s", componentName)); + throw new SecurityException(String.format("No active admin for %s", adminComponent)); } if (admin.getUid() != callerUid) { throw new SecurityException( - String.format("Admin %s is not owned by uid %d", componentName, callerUid)); + String.format("Admin %s is not owned by uid %d", adminComponent, callerUid)); } - return new CallerIdentity(callerUid, componentName.getPackageName(), componentName); + return new CallerIdentity(callerUid, adminComponent.getPackageName(), adminComponent); } /** @@ -4589,12 +4590,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - private void enforceDeviceOwner(ComponentName who) { - synchronized (getLockObject()) { - getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); - } - } - private void enforceProfileOrDeviceOwner(ComponentName who) { synchronized (getLockObject()) { getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); @@ -5194,20 +5189,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(who, "ComponentName is null"); Preconditions.checkStringNotEmpty(delegatePackage, "Delegate package is null or empty"); Preconditions.checkCollectionElementsNotNull(scopeList, "Scopes"); + final CallerIdentity identity = getCallerIdentity(who); + // Remove possible duplicates. final ArrayList<String> scopes = new ArrayList(new ArraySet(scopeList)); // Ensure given scopes are valid. if (scopes.retainAll(Arrays.asList(DELEGATIONS))) { throw new IllegalArgumentException("Unexpected delegation scopes"); } - final boolean hasDoDelegation = !Collections.disjoint(scopes, DEVICE_OWNER_DELEGATIONS); // Retrieve the user ID of the calling process. - final int userId = mInjector.userHandleGetCallingUserId(); + final int userId = identity.getUserId(); + final boolean hasDoDelegation = !Collections.disjoint(scopes, DEVICE_OWNER_DELEGATIONS); synchronized (getLockObject()) { // Ensure calling process is device/profile owner. if (hasDoDelegation) { - getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); } else { + // TODO move whole condition out of synchronized block getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); } // Ensure the delegate is installed (skip this for DELEGATION_CERT_INSTALL in pre-N). @@ -6199,7 +6197,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void setRecommendedGlobalProxy(ComponentName who, ProxyInfo proxyInfo) { - enforceDeviceOwner(who); + Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); mInjector.binderWithCleanCallingIdentity( () -> mInjector.getConnectivityManager().setGlobalProxy(proxyInfo)); } @@ -6620,6 +6620,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return; } Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); + // Allow setting this policy to true only if there is a split system user. if (forceEphemeralUsers && !mInjector.userManagerIsSplitSystemUser()) { throw new UnsupportedOperationException( @@ -6627,11 +6630,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } boolean removeAllUsers = false; synchronized (getLockObject()) { - final ActiveAdmin deviceOwner = - getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); if (deviceOwner.forceEphemeralUsers != forceEphemeralUsers) { deviceOwner.forceEphemeralUsers = forceEphemeralUsers; - saveSettingsLocked(mInjector.userHandleGetCallingUserId()); + saveSettingsLocked(identity.getUserId()); mUserManagerInternal.setForceEphemeralUsers(forceEphemeralUsers); removeAllUsers = forceEphemeralUsers; } @@ -6647,19 +6649,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } Objects.requireNonNull(who, "ComponentName is null"); - synchronized (getLockObject()) { - final ActiveAdmin deviceOwner = - getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); - return deviceOwner.forceEphemeralUsers; - } - } + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); - private void ensureDeviceOwnerAndAllUsersAffiliated(ComponentName who) - throws SecurityException { synchronized (getLockObject()) { - getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); + return deviceOwner.forceEphemeralUsers; } - ensureAllUsersAffiliated(); } private void ensureAllUsersAffiliated() throws SecurityException { @@ -6676,11 +6672,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } Objects.requireNonNull(who, "ComponentName is null"); - // TODO: If an unaffiliated user is removed, the admin will be able to request a bugreport // which could still contain data related to that user. Should we disallow that, e.g. until // next boot? Might not be needed given that this still requires user consent. - ensureDeviceOwnerAndAllUsersAffiliated(who); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); + ensureAllUsersAffiliated(); if (mRemoteBugreportServiceIsActive.get() || (getDeviceOwnerRemoteBugreportUri() != null)) { @@ -8489,6 +8486,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void setDefaultSmsApplication(ComponentName admin, String packageName, boolean parent) { Objects.requireNonNull(admin, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(admin); if (parent) { ActiveAdmin ap = getActiveAdminForCallerLocked(admin, @@ -8497,7 +8495,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mInjector.binderWithCleanCallingIdentity(() -> enforcePackageIsSystemPackage( packageName, getProfileParentId(mInjector.userHandleGetCallingUserId()))); } else { - enforceDeviceOwner(admin); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); } mInjector.binderWithCleanCallingIdentity(() -> @@ -9259,14 +9257,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { public boolean removeUser(ComponentName who, UserHandle userHandle) { Objects.requireNonNull(who, "ComponentName is null"); Objects.requireNonNull(userHandle, "UserHandle is null"); - enforceDeviceOwner(who); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); - final int callingUserId = mInjector.userHandleGetCallingUserId(); return mInjector.binderWithCleanCallingIdentity(() -> { String restriction = isManagedProfile(userHandle.getIdentifier()) ? UserManager.DISALLOW_REMOVE_MANAGED_PROFILE : UserManager.DISALLOW_REMOVE_USER; - if (isAdminAffectedByRestriction(who, restriction, callingUserId)) { + if (isAdminAffectedByRestriction(who, restriction, identity.getUserId())) { Log.w(LOG_TAG, "The device owner cannot remove a user because " + restriction + " is enabled, and was not set by the device owner"); return false; @@ -9292,10 +9290,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean switchUser(ComponentName who, UserHandle userHandle) { Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); synchronized (getLockObject()) { - getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); - long id = mInjector.binderClearCallingIdentity(); try { int userId = UserHandle.USER_SYSTEM; @@ -9316,7 +9314,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { public int startUserInBackground(ComponentName who, UserHandle userHandle) { Objects.requireNonNull(who, "ComponentName is null"); Objects.requireNonNull(userHandle, "UserHandle is null"); - enforceDeviceOwner(who); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); final int userId = userHandle.getIdentifier(); if (isManagedProfile(userId)) { @@ -9348,7 +9347,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { public int stopUser(ComponentName who, UserHandle userHandle) { Objects.requireNonNull(who, "ComponentName is null"); Objects.requireNonNull(userHandle, "UserHandle is null"); - enforceDeviceOwner(who); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); final int userId = userHandle.getIdentifier(); if (isManagedProfile(userId)) { @@ -9416,7 +9416,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public List<UserHandle> getSecondaryUsers(ComponentName who) { Objects.requireNonNull(who, "ComponentName is null"); - enforceDeviceOwner(who); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); return mInjector.binderWithCleanCallingIdentity(() -> { final List<UserInfo> userInfos = mInjector.getUserManager().getUsers(true @@ -10378,6 +10379,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void setGlobalSetting(ComponentName who, String setting, String value) { Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_GLOBAL_SETTING) @@ -10386,8 +10389,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { .write(); synchronized (getLockObject()) { - getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); - // Some settings are no supported any more. However we do not want to throw a // SecurityException to avoid breaking apps. if (GLOBAL_SETTINGS_DEPRECATED.contains(setting)) { @@ -10468,7 +10469,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void setLocationEnabled(ComponentName who, boolean locationEnabled) { - CallerIdentity identity = getCallerIdentity(who); + final CallerIdentity identity = getCallerIdentity(who); Preconditions.checkCallAuthorization(isDeviceOwner(identity)); mInjector.binderWithCleanCallingIdentity(() -> { @@ -12008,16 +12009,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean isSystemOnlyUser(ComponentName admin) { - enforceDeviceOwner(admin); - final int callingUserId = mInjector.userHandleGetCallingUserId(); - return UserManager.isSplitSystemUser() && callingUserId == UserHandle.USER_SYSTEM; + Objects.requireNonNull(admin, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(admin); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); + return UserManager.isSplitSystemUser() && identity.getUserId() == UserHandle.USER_SYSTEM; } @Override public void reboot(ComponentName admin) { - Objects.requireNonNull(admin); - // Make sure caller has DO. - enforceDeviceOwner(admin); + Objects.requireNonNull(admin, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(admin); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); + mInjector.binderWithCleanCallingIdentity(() -> { // Make sure there are no ongoing calls on the device. if (mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) { @@ -13523,18 +13526,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return; } - Objects.requireNonNull(admin); + Objects.requireNonNull(admin, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(admin); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); synchronized (getLockObject()) { - ActiveAdmin deviceOwner = - getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); - + ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); if (deviceOwner.isLogoutEnabled == enabled) { // already in the requested state return; } deviceOwner.isLogoutEnabled = enabled; - saveSettingsLocked(mInjector.userHandleGetCallingUserId()); + saveSettingsLocked(identity.getUserId()); } } @@ -13700,20 +13703,20 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return; } - Objects.requireNonNull(admin); + Objects.requireNonNull(admin, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(admin); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); final String startUserSessionMessageString = startUserSessionMessage != null ? startUserSessionMessage.toString() : null; synchronized (getLockObject()) { - final ActiveAdmin deviceOwner = - getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); - + final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); if (TextUtils.equals(deviceOwner.startUserSessionMessage, startUserSessionMessage)) { return; } deviceOwner.startUserSessionMessage = startUserSessionMessageString; - saveSettingsLocked(mInjector.userHandleGetCallingUserId()); + saveSettingsLocked(identity.getUserId()); } mInjector.getActivityManagerInternal() @@ -13725,20 +13728,20 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return; } - Objects.requireNonNull(admin); + Objects.requireNonNull(admin, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(admin); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); final String endUserSessionMessageString = endUserSessionMessage != null ? endUserSessionMessage.toString() : null; synchronized (getLockObject()) { - final ActiveAdmin deviceOwner = - getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); - + final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); if (TextUtils.equals(deviceOwner.endUserSessionMessage, endUserSessionMessage)) { return; } deviceOwner.endUserSessionMessage = endUserSessionMessageString; - saveSettingsLocked(mInjector.userHandleGetCallingUserId()); + saveSettingsLocked(identity.getUserId()); } mInjector.getActivityManagerInternal() @@ -13750,11 +13753,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return null; } - Objects.requireNonNull(admin); + Objects.requireNonNull(admin, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(admin); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); synchronized (getLockObject()) { - final ActiveAdmin deviceOwner = - getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); return deviceOwner.startUserSessionMessage; } } @@ -13764,11 +13768,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return null; } - Objects.requireNonNull(admin); + Objects.requireNonNull(admin, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(admin); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); synchronized (getLockObject()) { - final ActiveAdmin deviceOwner = - getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); return deviceOwner.endUserSessionMessage; } } @@ -13807,9 +13812,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature || !mHasTelephonyFeature) { return -1; } - Objects.requireNonNull(who, "ComponentName is null in addOverrideApn"); + Objects.requireNonNull(who, "ComponentName is null"); Objects.requireNonNull(apnSetting, "ApnSetting is null in addOverrideApn"); - enforceDeviceOwner(who); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); if (tm != null) { @@ -13827,9 +13833,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature || !mHasTelephonyFeature) { return false; } - Objects.requireNonNull(who, "ComponentName is null in updateOverrideApn"); + Objects.requireNonNull(who, "ComponentName is null"); Objects.requireNonNull(apnSetting, "ApnSetting is null in updateOverrideApn"); - enforceDeviceOwner(who); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); if (apnId < 0) { return false; @@ -13849,9 +13856,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature || !mHasTelephonyFeature) { return false; } - Objects.requireNonNull(who, "ComponentName is null in removeOverrideApn"); - enforceDeviceOwner(who); - + Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); return removeOverrideApnUnchecked(apnId); } @@ -13870,9 +13877,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature || !mHasTelephonyFeature) { return Collections.emptyList(); } - Objects.requireNonNull(who, "ComponentName is null in getOverrideApns"); - enforceDeviceOwner(who); - + Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); return getOverrideApnsUnchecked(); } @@ -13891,9 +13898,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature || !mHasTelephonyFeature) { return; } - Objects.requireNonNull(who, "ComponentName is null in setOverrideApnEnabled"); - enforceDeviceOwner(who); - + Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); setOverrideApnsEnabledUnchecked(enabled); } @@ -13909,8 +13916,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature || !mHasTelephonyFeature) { return false; } - Objects.requireNonNull(who, "ComponentName is null in isOverrideApnEnabled"); - enforceDeviceOwner(who); + Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); Cursor enforceCursor = mInjector.binderWithCleanCallingIdentity( () -> mContext.getContentResolver().query( @@ -13992,11 +14000,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return PRIVATE_DNS_SET_ERROR_FAILURE_SETTING; } - Objects.requireNonNull(who, "ComponentName is null"); - enforceDeviceOwner(who); - - final int returnCode; + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); switch (mode) { case PRIVATE_DNS_MODE_OPPORTUNISTIC: @@ -14030,9 +14036,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return PRIVATE_DNS_MODE_UNKNOWN; } - Objects.requireNonNull(who, "ComponentName is null"); - enforceDeviceOwner(who); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); + String currentMode = mInjector.settingsGlobalGetString(PRIVATE_DNS_MODE); if (currentMode == null) { currentMode = ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE_FALLBACK; @@ -14054,10 +14061,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return null; } - Objects.requireNonNull(who, "ComponentName is null"); - enforceDeviceOwner(who); - + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); return mInjector.settingsGlobalGetString(PRIVATE_DNS_SPECIFIER); } @@ -14402,13 +14408,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void setUserControlDisabledPackages(ComponentName who, List<String> packages) { - Preconditions.checkNotNull(who, "ComponentName is null"); + Objects.requireNonNull(who, "ComponentName is null"); Preconditions.checkNotNull(packages, "packages is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); - enforceDeviceOwner(who); synchronized (getLockObject()) { - final int userHandle = mInjector.userHandleGetCallingUserId(); - setUserControlDisabledPackagesLocked(userHandle, packages); + setUserControlDisabledPackagesLocked(identity.getUserId(), packages); DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_USER_CONTROL_DISABLED_PACKAGES) .setAdmin(who) @@ -14428,12 +14434,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public List<String> getUserControlDisabledPackages(ComponentName who) { - Preconditions.checkNotNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity)); - enforceDeviceOwner(who); - final int userHandle = mInjector.binderGetCallingUserHandle().getIdentifier(); synchronized (getLockObject()) { - final List<String> packages = getUserData(userHandle).mUserControlDisabledPackages; + final List<String> packages = + getUserData(identity.getUserId()).mUserControlDisabledPackages; return packages == null ? Collections.EMPTY_LIST : packages; } } diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java index e8266a574bf5..b93c519ec8e4 100644 --- a/services/print/java/com/android/server/print/UserState.java +++ b/services/print/java/com/android/server/print/UserState.java @@ -30,6 +30,7 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; @@ -132,7 +133,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks, private final Context mContext; - private final int mUserId; + private final @UserIdInt int mUserId; private final RemotePrintSpooler mSpooler; @@ -650,7 +651,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks, mPrintServiceRecommendationsService = new RemotePrintServiceRecommendationService(mContext, - UserHandle.getUserHandleForUid(mUserId), this); + UserHandle.of(mUserId), this); } mPrintServiceRecommendationsChangeListenerRecords.add( new ListenerRecord<IRecommendationsChangeListener>(listener) { diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java index bc75dcd91813..12c69eaa0f8d 100644 --- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java @@ -150,7 +150,8 @@ public final class ProfcollectForwardingService extends SystemService { } // Sample for a fraction of app launches. - int traceFrequency = SystemProperties.getInt("profcollectd.applaunch_trace_freq", 2); + int traceFrequency = + SystemProperties.getInt("persist.profcollectd.applaunch_trace_freq", 2); int randomNum = ThreadLocalRandom.current().nextInt(100); if (randomNum < traceFrequency) { try { diff --git a/services/tests/PackageManagerServiceTests/host/Android.bp b/services/tests/PackageManagerServiceTests/host/Android.bp index e4e7e2288590..4f636efc7c06 100644 --- a/services/tests/PackageManagerServiceTests/host/Android.bp +++ b/services/tests/PackageManagerServiceTests/host/Android.bp @@ -22,6 +22,7 @@ java_test_host { ], static_libs: [ "frameworks-base-hostutils", + "PackageManagerServiceHostTestsIntentVerifyUtils", ], test_suites: ["general-tests"], java_resources: [ @@ -33,7 +34,15 @@ java_test_host { ":PackageManagerTestAppVersion4", ":PackageManagerTestAppOriginalOverride", ":PackageManagerServiceDeviceSideTests", - ], + ":PackageManagerTestIntentVerifier", + ":PackageManagerTestIntentVerifierTarget1", + ":PackageManagerTestIntentVerifierTarget2", + ":PackageManagerTestIntentVerifierTarget3", + ":PackageManagerTestIntentVerifierTarget4Base", + ":PackageManagerTestIntentVerifierTarget4NoAutoVerify", + ":PackageManagerTestIntentVerifierTarget4Wildcard", + ":PackageManagerTestIntentVerifierTarget4WildcardNoAutoVerify", + ] } genrule { diff --git a/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/Android.bp b/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/Android.bp new file mode 100644 index 000000000000..b7a0624e02b8 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/Android.bp @@ -0,0 +1,19 @@ +// 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. + +java_library { + name: "PackageManagerServiceHostTestsIntentVerifyUtils", + srcs: ["src/**/*.kt"], + host_supported: true, +} diff --git a/tests/AutoVerify/app4/src/com/android/test/autoverify/MainActivity.java b/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/src/com/android/server/pm/test/intent/verify/IntentVerifyTestParams.kt index 09ef47212622..48119e0088c4 100644 --- a/tests/AutoVerify/app4/src/com/android/test/autoverify/MainActivity.java +++ b/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/src/com/android/server/pm/test/intent/verify/IntentVerifyTestParams.kt @@ -13,3 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +package com.android.server.pm.test.intent.verify + +interface IntentVerifyTestParams { + + val methodName: String + + fun toArgsMap(): Map<String, String> +} diff --git a/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/src/com/android/server/pm/test/intent/verify/SetActivityAsAlwaysParams.kt b/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/src/com/android/server/pm/test/intent/verify/SetActivityAsAlwaysParams.kt new file mode 100644 index 000000000000..26c3903b20d6 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/src/com/android/server/pm/test/intent/verify/SetActivityAsAlwaysParams.kt @@ -0,0 +1,43 @@ +/* + * 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.server.pm.test.intent.verify + +data class SetActivityAsAlwaysParams( + val uri: String, + val packageName: String, + val activityName: String, + override val methodName: String = "setActivityAsAlways" +) : IntentVerifyTestParams { + + companion object { + private const val KEY_URI = "uri" + private const val KEY_PACKAGE_NAME = "packageName" + private const val KEY_ACTIVITY_NAME = "activityName" + + fun fromArgs(args: Map<String, String>) = SetActivityAsAlwaysParams( + args.getValue(KEY_URI), + args.getValue(KEY_PACKAGE_NAME), + args.getValue(KEY_ACTIVITY_NAME) + ) + } + + override fun toArgsMap() = mapOf( + KEY_URI to uri, + KEY_PACKAGE_NAME to packageName, + KEY_ACTIVITY_NAME to activityName + ) +} diff --git a/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/src/com/android/server/pm/test/intent/verify/StartActivityParams.kt b/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/src/com/android/server/pm/test/intent/verify/StartActivityParams.kt new file mode 100644 index 000000000000..7eddcfb621c4 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/src/com/android/server/pm/test/intent/verify/StartActivityParams.kt @@ -0,0 +1,48 @@ +/* + * 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.server.pm.test.intent.verify + +data class StartActivityParams( + val uri: String, + val expected: List<String>, + val withBrowsers: Boolean = false, + override val methodName: String = "verifyActivityStart" +) : IntentVerifyTestParams { + companion object { + private const val KEY_URI = "uri" + private const val KEY_EXPECTED = "expected" + private const val KEY_BROWSER = "browser" + + fun fromArgs(args: Map<String, String>) = StartActivityParams( + args.getValue(KEY_URI), + args.getValue(KEY_EXPECTED).split(","), + args.getValue(KEY_BROWSER).toBoolean() + ) + } + + constructor( + uri: String, + expected: String, + withBrowsers: Boolean = false + ) : this(uri, listOf(expected), withBrowsers) + + override fun toArgsMap() = mapOf( + KEY_URI to uri, + KEY_EXPECTED to expected.joinToString(separator = ","), + KEY_BROWSER to withBrowsers.toString() + ) +} diff --git a/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/src/com/android/server/pm/test/intent/verify/VerifyRequest.kt b/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/src/com/android/server/pm/test/intent/verify/VerifyRequest.kt new file mode 100644 index 000000000000..f93b1e0e7e37 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/src/com/android/server/pm/test/intent/verify/VerifyRequest.kt @@ -0,0 +1,48 @@ +/* + * 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.server.pm.test.intent.verify + +data class VerifyRequest( + val id: Int = -1, + val scheme: String, + val hosts: List<String>, + val packageName: String +) { + + companion object { + fun deserialize(value: String?): VerifyRequest { + val lines = value?.trim()?.lines() + ?: return VerifyRequest(scheme = "", hosts = emptyList(), packageName = "") + return VerifyRequest( + lines[0].removePrefix("id=").toInt(), + lines[1].removePrefix("scheme="), + lines[2].removePrefix("hosts=").split(","), + lines[3].removePrefix("packageName=") + ) + } + } + + constructor(id: Int = -1, scheme: String, host: String, packageName: String) : + this(id, scheme, listOf(host), packageName) + + fun serializeToString() = """ + id=$id + scheme=$scheme + hosts=${hosts.joinToString(separator = ",")} + packageName=$packageName + """.trimIndent() + "\n" +} diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/FactoryPackageTest.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/FactoryPackageTest.kt index 3847658def6a..e17358d38d8c 100644 --- a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/FactoryPackageTest.kt +++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/FactoryPackageTest.kt @@ -31,7 +31,8 @@ class FactoryPackageTest : BaseHostJUnit4Test() { private val preparer: SystemPreparer = SystemPreparer(tempFolder, SystemPreparer.RebootStrategy.FULL, deviceRebootRule) { this.device } - @get:Rule + @Rule + @JvmField val rules = RuleChain.outerRule(tempFolder).around(preparer)!! private val filePath = HostUtils.makePathForApk("PackageManagerTestApp.apk", Partition.SYSTEM) diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt index 8dfefaf9750f..24c714c0d5f2 100644 --- a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt +++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt @@ -18,6 +18,7 @@ package com.android.server.pm.test import com.android.internal.util.test.SystemPreparer import com.android.tradefed.device.ITestDevice +import org.junit.rules.TemporaryFolder import java.io.File import java.io.FileOutputStream @@ -34,6 +35,19 @@ internal fun SystemPreparer.deleteApkFolders( } } +internal fun ITestDevice.installJavaResourceApk( + tempFolder: TemporaryFolder, + javaResource: String, + reinstall: Boolean = true, + extraArgs: Array<String> = emptyArray() +): String? { + val file = HostUtils.copyResourceToHostFile(javaResource, tempFolder.newFile()) + return installPackage(file, reinstall, *extraArgs) +} + +internal fun ITestDevice.uninstallPackages(vararg pkgNames: String) = + pkgNames.forEach { uninstallPackage(it) } + internal object HostUtils { fun getDataDir(device: ITestDevice, pkgName: String) = diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/InvalidNewSystemAppTest.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/InvalidNewSystemAppTest.kt index b7d135991ccd..37c999cbee68 100644 --- a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/InvalidNewSystemAppTest.kt +++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/InvalidNewSystemAppTest.kt @@ -47,7 +47,8 @@ class InvalidNewSystemAppTest : BaseHostJUnit4Test() { private val preparer: SystemPreparer = SystemPreparer(tempFolder, SystemPreparer.RebootStrategy.FULL, deviceRebootRule) { this.device } - @get:Rule + @Rule + @JvmField val rules = RuleChain.outerRule(tempFolder).around(preparer)!! private val filePath = HostUtils.makePathForApk("PackageManagerTestApp.apk", Partition.PRODUCT) diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/OriginalPackageMigrationTest.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/OriginalPackageMigrationTest.kt index 4ae3ca5f7263..4becae66633f 100644 --- a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/OriginalPackageMigrationTest.kt +++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/OriginalPackageMigrationTest.kt @@ -47,7 +47,8 @@ class OriginalPackageMigrationTest : BaseHostJUnit4Test() { private val preparer: SystemPreparer = SystemPreparer(tempFolder, SystemPreparer.RebootStrategy.FULL, deviceRebootRule) { this.device } - @get:Rule + @Rule + @JvmField val rules = RuleChain.outerRule(tempFolder).around(preparer)!! @Before diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/Partition.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/Partition.kt index 654c11c5bf81..6479f584324f 100644 --- a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/Partition.kt +++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/Partition.kt @@ -22,6 +22,7 @@ import java.nio.file.Paths // Unfortunately no easy way to access PMS SystemPartitions, so mock them here internal enum class Partition(val baseAppFolder: Path) { SYSTEM("/system/app"), + SYSTEM_PRIVILEGED("/system/priv-app"), VENDOR("/vendor/app"), PRODUCT("/product/app"), SYSTEM_EXT("/system_ext/app") diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt index 207f10a3027b..46120af06550 100644 --- a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt +++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt @@ -110,7 +110,8 @@ class SystemStubMultiUserDisableUninstallTest : BaseHostJUnit4Test() { private val preparer: SystemPreparer = SystemPreparer(tempFolder, SystemPreparer.RebootStrategy.FULL, deviceRebootRule) { this.device } - @get:Rule + @Rule + @JvmField val rules = RuleChain.outerRule(tempFolder).let { if (DEBUG_NO_REBOOT) { it!! diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/intent/verify/IntentFilterVerificationTest.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/intent/verify/IntentFilterVerificationTest.kt new file mode 100644 index 000000000000..fffda8ebd36c --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/intent/verify/IntentFilterVerificationTest.kt @@ -0,0 +1,413 @@ +/* + * 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.server.pm.test.intent.verify + +import com.android.internal.util.test.SystemPreparer +import com.android.server.pm.test.Partition +import com.android.server.pm.test.deleteApkFolders +import com.android.server.pm.test.installJavaResourceApk +import com.android.server.pm.test.pushApk +import com.android.server.pm.test.uninstallPackages +import com.android.tradefed.testtype.DeviceJUnit4ClassRunner +import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test +import com.google.common.truth.Truth.assertThat +import org.junit.After +import org.junit.Before +import org.junit.ClassRule +import org.junit.Rule +import org.junit.Test +import org.junit.rules.RuleChain +import org.junit.rules.TemporaryFolder +import org.junit.runner.RunWith +import java.io.File +import java.util.concurrent.TimeUnit + +@RunWith(DeviceJUnit4ClassRunner::class) +class IntentFilterVerificationTest : BaseHostJUnit4Test() { + + companion object { + private const val VERIFIER = "PackageManagerTestIntentVerifier.apk" + private const val VERIFIER_PKG_NAME = "com.android.server.pm.test.intent.verifier" + private const val TARGET_PKG_PREFIX = "$VERIFIER_PKG_NAME.target" + private const val TARGET_APK_PREFIX = "PackageManagerTestIntentVerifierTarget" + private const val TARGET_ONE = "${TARGET_APK_PREFIX}1.apk" + private const val TARGET_ONE_PKG_NAME = "$TARGET_PKG_PREFIX.one" + private const val TARGET_TWO = "${TARGET_APK_PREFIX}2.apk" + private const val TARGET_TWO_PKG_NAME = "$TARGET_PKG_PREFIX.two" + private const val TARGET_THREE = "${TARGET_APK_PREFIX}3.apk" + private const val TARGET_THREE_PKG_NAME = "$TARGET_PKG_PREFIX.three" + private const val TARGET_FOUR_BASE = "${TARGET_APK_PREFIX}4Base.apk" + private const val TARGET_FOUR_PKG_NAME = "$TARGET_PKG_PREFIX.four" + private const val TARGET_FOUR_NO_AUTO_VERIFY = "${TARGET_APK_PREFIX}4NoAutoVerify.apk" + private const val TARGET_FOUR_WILDCARD = "${TARGET_APK_PREFIX}4Wildcard.apk" + private const val TARGET_FOUR_WILDCARD_NO_AUTO_VERIFY = + "${TARGET_APK_PREFIX}4WildcardNoAutoVerify.apk" + + @get:ClassRule + val deviceRebootRule = SystemPreparer.TestRuleDelegate(true) + } + + private val tempFolder = TemporaryFolder() + private val preparer: SystemPreparer = SystemPreparer(tempFolder, + SystemPreparer.RebootStrategy.FULL, deviceRebootRule) { this.device } + + @Rule + @JvmField + val rules = RuleChain.outerRule(tempFolder).around(preparer)!! + + private val permissionsFile = File("/system/etc/permissions" + + "/privapp-PackageManagerIntentFilterVerificationTest-permissions.xml") + + @Before + fun cleanupAndPushPermissionsFile() { + // In order for the test app to be the verification agent, it needs a permission file + // which can be pushed onto the system and removed afterwards. + val file = tempFolder.newFile().apply { + """ + <permissions> + <privapp-permissions package="$VERIFIER_PKG_NAME"> + <permission name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"/> + </privapp-permissions> + </permissions> + """ + .trimIndent() + .let { writeText(it) } + } + device.uninstallPackages(TARGET_ONE_PKG_NAME, TARGET_TWO_PKG_NAME, TARGET_THREE_PKG_NAME, + TARGET_FOUR_PKG_NAME) + preparer.pushApk(VERIFIER, Partition.SYSTEM_PRIVILEGED) + .pushFile(file, permissionsFile.toString()) + .reboot() + runTest("clearResponse") + } + + @After + fun cleanupAndDeletePermissionsFile() { + device.uninstallPackages(TARGET_ONE_PKG_NAME, TARGET_TWO_PKG_NAME, TARGET_THREE_PKG_NAME, + TARGET_FOUR_PKG_NAME) + preparer.deleteApkFolders(Partition.SYSTEM_PRIVILEGED, VERIFIER) + .deleteFile(permissionsFile.toString()) + device.reboot() + } + + @Test + fun verifyOne() { + installPackage(TARGET_ONE) + + assertReceivedRequests(true, VerifyRequest( + scheme = "https", + hosts = listOf( + "https_only.pm.server.android.com", + "other_activity.pm.server.android.com", + "http_only.pm.server.android.com", + "verify.pm.server.android.com", + "https_plus_non_web_scheme.pm.server.android.com", + "multiple.pm.server.android.com", + // TODO(b/159952358): the following domain should not be + // verified, this is because the verifier tries to verify all web domains, + // even in intent filters not marked for auto verify + "no_verify.pm.server.android.com" + ), + packageName = TARGET_ONE_PKG_NAME + )) + + runTest(StartActivityParams( + uri = "https://https_only.pm.server.android.com", + expected = "$TARGET_ONE_PKG_NAME.TargetActivity" + )) + } + + @Test + fun nonWebScheme() { + installPackage(TARGET_TWO) + assertReceivedRequests(null) + } + + @Test + fun verifyHttpNonSecureOnly() { + installPackage(TARGET_THREE) + assertReceivedRequests(true, VerifyRequest( + scheme = "https", + hosts = listOf( + "multiple.pm.server.android.com" + ), + packageName = TARGET_THREE_PKG_NAME + )) + + runTest(StartActivityParams( + uri = "http://multiple.pm.server.android.com", + expected = "$TARGET_THREE_PKG_NAME.TargetActivity" + )) + } + + @Test + fun multipleResults() { + installPackage(TARGET_ONE) + installPackage(TARGET_THREE) + assertReceivedRequests(true, VerifyRequest( + scheme = "https", + hosts = listOf( + "https_only.pm.server.android.com", + "other_activity.pm.server.android.com", + "http_only.pm.server.android.com", + "verify.pm.server.android.com", + "https_plus_non_web_scheme.pm.server.android.com", + "multiple.pm.server.android.com", + // TODO(b/159952358): the following domain should not be + // verified, this is because the verifier tries to verify all web domains, + // even in intent filters not marked for auto verify + "no_verify.pm.server.android.com" + ), + packageName = TARGET_ONE_PKG_NAME + ), VerifyRequest( + scheme = "https", + hosts = listOf( + "multiple.pm.server.android.com" + ), + packageName = TARGET_THREE_PKG_NAME + )) + + // Target3 declares http non-s, so it should be included in the set here + runTest(StartActivityParams( + uri = "http://multiple.pm.server.android.com", + expected = listOf( + "$TARGET_ONE_PKG_NAME.TargetActivity2", + "$TARGET_THREE_PKG_NAME.TargetActivity" + ) + )) + + // But it excludes https, so it shouldn't resolve here + runTest(StartActivityParams( + uri = "https://multiple.pm.server.android.com", + expected = "$TARGET_ONE_PKG_NAME.TargetActivity2" + )) + + // Remove Target3 and return to single verified Target1 app for http non-s + device.uninstallPackage(TARGET_THREE_PKG_NAME) + runTest(StartActivityParams( + uri = "http://multiple.pm.server.android.com", + expected = "$TARGET_ONE_PKG_NAME.TargetActivity2" + )) + } + + @Test + fun demoteAlways() { + installPackage(TARGET_FOUR_BASE) + assertReceivedRequests(false, VerifyRequest( + scheme = "https", + host = "failing.pm.server.android.com", + packageName = TARGET_FOUR_PKG_NAME + )) + + runTest(StartActivityParams( + uri = "https://failing.pm.server.android.com", + expected = "$TARGET_FOUR_PKG_NAME.TargetActivity", + withBrowsers = true + )) + runTest(SetActivityAsAlwaysParams( + uri = "https://failing.pm.server.android.com", + packageName = TARGET_FOUR_PKG_NAME, + activityName = "$TARGET_FOUR_PKG_NAME.TargetActivity" + )) + runTest(StartActivityParams( + uri = "https://failing.pm.server.android.com", + expected = "$TARGET_FOUR_PKG_NAME.TargetActivity" + )) + + // Re-installing with same host/verify set will maintain always setting + installPackage(TARGET_FOUR_BASE) + assertReceivedRequests(null) + runTest(StartActivityParams( + uri = "https://failing.pm.server.android.com", + expected = "$TARGET_FOUR_PKG_NAME.TargetActivity" + )) + + // Installing with new wildcard host will downgrade out of always, re-including browsers + installPackage(TARGET_FOUR_WILDCARD) + + // TODO(b/159952358): The first request without the wildcard should not be sent. This is + // caused by the request being queued even if it should be dropped from the previous + // install case since the host set didn't change. + assertReceivedRequests(false, VerifyRequest( + scheme = "https", + hosts = listOf("failing.pm.server.android.com"), + packageName = TARGET_FOUR_PKG_NAME + ), VerifyRequest( + scheme = "https", + hosts = listOf("failing.pm.server.android.com", "wildcard.tld"), + packageName = TARGET_FOUR_PKG_NAME + )) + runTest(StartActivityParams( + uri = "https://failing.pm.server.android.com", + expected = "$TARGET_FOUR_PKG_NAME.TargetActivity", + withBrowsers = true + )) + } + + @Test + fun unverifiedReinstallResendRequest() { + installPackage(TARGET_FOUR_BASE) + assertReceivedRequests(false, VerifyRequest( + scheme = "https", + host = "failing.pm.server.android.com", + packageName = TARGET_FOUR_PKG_NAME + )) + + installPackage(TARGET_FOUR_BASE) + + assertReceivedRequests(false, VerifyRequest( + scheme = "https", + host = "failing.pm.server.android.com", + packageName = TARGET_FOUR_PKG_NAME + )) + } + + @Test + fun unverifiedUpdateRemovingDomainNoRequestDemoteAlways() { + installPackage(TARGET_FOUR_WILDCARD) + assertReceivedRequests(false, VerifyRequest( + scheme = "https", + hosts = listOf("failing.pm.server.android.com", "wildcard.tld"), + packageName = TARGET_FOUR_PKG_NAME + )) + + runTest(SetActivityAsAlwaysParams( + uri = "https://failing.pm.server.android.com", + packageName = TARGET_FOUR_PKG_NAME, + activityName = "$TARGET_FOUR_PKG_NAME.TargetActivity" + )) + + // Re-installing with a smaller host/verify set will not request re-verification + installPackage(TARGET_FOUR_BASE) + assertReceivedRequests(null) + runTest(StartActivityParams( + uri = "https://failing.pm.server.android.com", + expected = "$TARGET_FOUR_PKG_NAME.TargetActivity" + )) + + // Re-installing with a (now) larger host/verify set will re-request and demote + installPackage(TARGET_FOUR_WILDCARD) + // TODO(b/159952358): The first request should not be sent. This is caused by the request + // being queued even if it should be dropped from the previous install case. + assertReceivedRequests(false, VerifyRequest( + scheme = "https", + host = "failing.pm.server.android.com", + packageName = TARGET_FOUR_PKG_NAME + ), VerifyRequest( + scheme = "https", + hosts = listOf("failing.pm.server.android.com", "wildcard.tld"), + packageName = TARGET_FOUR_PKG_NAME + )) + + runTest(StartActivityParams( + uri = "https://failing.pm.server.android.com", + expected = "$TARGET_FOUR_PKG_NAME.TargetActivity", + withBrowsers = true + )) + } + + // TODO(b/159952358): I would expect this to demote + // TODO(b/32810168) + @Test + fun verifiedUpdateRemovingAutoVerifyMaintainsAlways() { + installPackage(TARGET_FOUR_BASE) + assertReceivedRequests(true, VerifyRequest( + scheme = "https", + host = "failing.pm.server.android.com", + packageName = TARGET_FOUR_PKG_NAME + )) + + runTest(StartActivityParams( + uri = "https://failing.pm.server.android.com", + expected = "$TARGET_FOUR_PKG_NAME.TargetActivity" + )) + + installPackage(TARGET_FOUR_NO_AUTO_VERIFY) + assertReceivedRequests(null) + + runTest(StartActivityParams( + uri = "https://failing.pm.server.android.com", + expected = "$TARGET_FOUR_PKG_NAME.TargetActivity" + )) + } + + @Test + fun verifiedUpdateRemovingAutoVerifyAddingDomainDemotesAlways() { + installPackage(TARGET_FOUR_BASE) + + assertReceivedRequests(true, VerifyRequest( + scheme = "https", + host = "failing.pm.server.android.com", + packageName = TARGET_FOUR_PKG_NAME + )) + + runTest(StartActivityParams( + uri = "https://failing.pm.server.android.com", + expected = "$TARGET_FOUR_PKG_NAME.TargetActivity" + )) + + installPackage(TARGET_FOUR_WILDCARD_NO_AUTO_VERIFY) + assertReceivedRequests(null) + + runTest(StartActivityParams( + uri = "https://failing.pm.server.android.com", + expected = "$TARGET_FOUR_PKG_NAME.TargetActivity", + withBrowsers = true + )) + } + + private fun installPackage(javaResourceName: String) { + // Need to pass --user as verification is not currently run for all user installs + assertThat(device.installJavaResourceApk(tempFolder, javaResourceName, + extraArgs = arrayOf("--user", device.currentUser.toString()))).isNull() + } + + private fun assertReceivedRequests(success: Boolean?, vararg expected: VerifyRequest?) { + // TODO(b/159952358): This can probably be less than 10 + // Because tests have to assert that multiple broadcasts aren't received, there's no real + // better way to await for a value than sleeping for a long enough time. + TimeUnit.SECONDS.sleep(10) + + val params = mutableMapOf<String, String>() + if (expected.any { it != null }) { + params["expected"] = expected.filterNotNull() + .joinToString(separator = "") { it.serializeToString() } + } + runTest("compareLastReceived", params) + + if (success != null) { + if (success) { + runTest("verifyPreviousReceivedSuccess") + } else { + runTest("verifyPreviousReceivedFailure") + } + runTest("clearResponse") + } + } + + private fun runTest(params: IntentVerifyTestParams) = + runTest(params.methodName, params.toArgsMap()) + + private fun runTest(testName: String, args: Map<String, String> = emptyMap()) { + val escapedArgs = args.mapValues { + // Need to escape strings so that args are passed properly through the shell command + "\"${it.value.trim('"')}\"" + } + runDeviceTests(device, null, VERIFIER_PKG_NAME, "$VERIFIER_PKG_NAME.VerifyReceiverTest", + testName, null, 10 * 60 * 1000L, 10 * 60 * 1000L, 0L, true, false, escapedArgs) + } +} diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/Android.bp new file mode 100644 index 000000000000..e82f57d20fcc --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/Android.bp @@ -0,0 +1,28 @@ +// 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_test_helper_app { + name: "PackageManagerTestIntentVerifier", + srcs: [ "src/**/*.kt" ], + static_libs: [ + "androidx.test.core", + "androidx.test.espresso.core", + "androidx.test.runner", + "compatibility-device-util-axt", + "junit", + "truth-prebuilt", + "PackageManagerServiceHostTestsIntentVerifyUtils", + ], + platform_apis: true, +} diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/AndroidManifest.xml b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/AndroidManifest.xml new file mode 100644 index 000000000000..17b50b0ec949 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/AndroidManifest.xml @@ -0,0 +1,38 @@ +<?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. + --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.server.pm.test.intent.verifier" + > + + <uses-permission android:name="android.permission.INTENT_FILTER_VERIFICATION_AGENT" /> + <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> + <uses-permission android:name="android.permission.SET_PREFERRED_APPLICATIONS" /> + + <instrumentation + android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.server.pm.test.intent.verifier" + /> + + <application> + <receiver android:name=".VerifyReceiver" android:exported="true"> + <intent-filter android:priority="999"> + <action android:name="android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION"/> + <data android:mimeType="application/vnd.android.package-archive"/> + </intent-filter> + </receiver> + </application> + +</manifest> diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/src/com/android/server/pm/test/intent/verifier/VerifyReceiver.kt b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/src/com/android/server/pm/test/intent/verifier/VerifyReceiver.kt new file mode 100644 index 000000000000..073c2be75424 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/src/com/android/server/pm/test/intent/verifier/VerifyReceiver.kt @@ -0,0 +1,62 @@ +/* + * 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.server.pm.test.intent.verifier + +import android.content.BroadcastReceiver +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import com.android.server.pm.test.intent.verify.VerifyRequest + +class VerifyReceiver : BroadcastReceiver() { + + override fun onReceive(context: Context, intent: Intent) { + if (intent.action != Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION) return + val params = intent.toVerifyParams() + + // If the receiver is called for a normal request, proxy it to the real verifier on device + if (params.hosts.none { it.contains("pm.server.android.com") }) { + sendToRealVerifier(context, Intent(intent)) + return + } + + // When the receiver is invoked for a test install, there is no direct connection to host, + // so store the result in a file to read and assert on later. Append is intentional so that + // amount of invocations and clean up can be verified. + context.filesDir.resolve("test.txt") + .appendText(params.serializeToString()) + } + + private fun sendToRealVerifier(context: Context, intent: Intent) { + context.packageManager.queryBroadcastReceivers(intent, 0) + .first { it.activityInfo?.packageName != context.packageName } + .let { it.activityInfo!! } + .let { intent.setComponent(ComponentName(it.packageName, it.name)) } + .run { context.sendBroadcast(intent) } + } + + private fun Intent.toVerifyParams() = VerifyRequest( + id = getIntExtra(PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_ID, -1), + scheme = getStringExtra(PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_URI_SCHEME)!!, + hosts = getStringExtra(PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_HOSTS)!! + .split(' '), + packageName = getStringExtra( + PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_PACKAGE_NAME)!! + + ) +} diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/src/com/android/server/pm/test/intent/verifier/VerifyReceiverTest.kt b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/src/com/android/server/pm/test/intent/verifier/VerifyReceiverTest.kt new file mode 100644 index 000000000000..6de3d4e160ec --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/src/com/android/server/pm/test/intent/verifier/VerifyReceiverTest.kt @@ -0,0 +1,160 @@ +/* + * 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.server.pm.test.intent.verifier + +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.content.pm.PackageManager +import android.net.Uri +import android.os.Bundle +import android.os.UserHandle +import androidx.test.InstrumentationRegistry +import androidx.test.runner.AndroidJUnit4 +import com.android.compatibility.common.util.ShellIdentityUtils +import com.android.server.pm.test.intent.verify.SetActivityAsAlwaysParams +import com.android.server.pm.test.intent.verify.StartActivityParams +import com.android.server.pm.test.intent.verify.VerifyRequest +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import java.io.File + +@RunWith(AndroidJUnit4::class) +class VerifyReceiverTest { + + val args: Bundle = InstrumentationRegistry.getArguments() + val context: Context = InstrumentationRegistry.getContext() + + private val file = context.filesDir.resolve("test.txt") + + @Test + fun clearResponse() { + file.delete() + } + + @Test + fun compareLastReceived() { + val lastReceivedText = file.readTextIfExists() + val expectedText = args.getString("expected") + if (expectedText.isNullOrEmpty()) { + assertThat(lastReceivedText).isEmpty() + return + } + + val expectedParams = expectedText.parseParams() + val lastReceivedParams = lastReceivedText.parseParams() + + assertThat(lastReceivedParams).hasSize(expectedParams.size) + + lastReceivedParams.zip(expectedParams).forEach { (actual, expected) -> + assertThat(actual.hosts).containsExactlyElementsIn(expected.hosts) + assertThat(actual.packageName).isEqualTo(expected.packageName) + assertThat(actual.scheme).isEqualTo(expected.scheme) + } + } + + @Test + fun setActivityAsAlways() { + val params = SetActivityAsAlwaysParams.fromArgs( + args.keySet().associateWith { args.getString(it)!! }) + val uri = Uri.parse(params.uri) + val filter = IntentFilter().apply { + addAction(Intent.ACTION_VIEW) + addCategory(Intent.CATEGORY_DEFAULT) + addDataScheme(uri.scheme) + addDataAuthority(uri.authority, null) + } + + val intent = Intent(Intent.ACTION_VIEW, uri).apply { + addCategory(Intent.CATEGORY_DEFAULT) + } + val allResults = context.packageManager.queryIntentActivities(intent, 0) + val allComponents = allResults + .map { ComponentName(it.activityInfo.packageName, it.activityInfo.name) } + .toTypedArray() + val matchingInfo = allResults.first { + it.activityInfo.packageName == params.packageName && + it.activityInfo.name == params.activityName + } + + ShellIdentityUtils.invokeMethodWithShellPermissions(context.packageManager, + ShellIdentityUtils.ShellPermissionMethodHelper<Unit, PackageManager> { + it.addUniquePreferredActivity(filter, matchingInfo.match, allComponents, + ComponentName(matchingInfo.activityInfo.packageName, + matchingInfo.activityInfo.name)) + it.updateIntentVerificationStatusAsUser(params.packageName, + PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS, + UserHandle.myUserId()) + }, "android.permission.SET_PREFERRED_APPLICATIONS") + } + + @Test + fun verifyPreviousReceivedSuccess() { + file.readTextIfExists() + .parseParams() + .forEach { + context.packageManager.verifyIntentFilter(it.id, + PackageManager.INTENT_FILTER_VERIFICATION_SUCCESS, emptyList()) + } + } + + @Test + fun verifyPreviousReceivedFailure() { + file.readTextIfExists() + .parseParams() + .forEach { + context.packageManager.verifyIntentFilter(it.id, + PackageManager.INTENT_FILTER_VERIFICATION_FAILURE, it.hosts) + } + } + + @Test + fun verifyActivityStart() { + val params = StartActivityParams + .fromArgs(args.keySet().associateWith { args.getString(it)!! }) + val uri = Uri.parse(params.uri) + val intent = Intent(Intent.ACTION_VIEW).apply { + data = uri + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + + val expectedActivities = params.expected.toMutableList() + + if (params.withBrowsers) { + // Since the host doesn't know what browsers the device has, query here and add it to + // set if it's expected that browser are returned + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse("https://example.com")) + expectedActivities += context.packageManager.queryIntentActivities(browserIntent, 0) + .map { it.activityInfo.name } + } + + val infos = context.packageManager.queryIntentActivities(intent, 0) + .map { it.activityInfo.name } + assertThat(infos).containsExactlyElementsIn(expectedActivities) + } + + private fun File.readTextIfExists() = if (exists()) readText() else "" + + // Rudimentary list deserialization by splitting text block into 4 line sections + private fun String.parseParams() = trim() + .lines() + .windowed(4, 4) + .map { it.joinToString(separator = "\n") } + .map { VerifyRequest.deserialize(it) } +} diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/Android.bp new file mode 100644 index 000000000000..7161fdd33516 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/Android.bp @@ -0,0 +1,48 @@ +// 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_test_helper_app { + name: "PackageManagerTestIntentVerifierTarget1", + manifest: "AndroidManifest1.xml", +} + +android_test_helper_app { + name: "PackageManagerTestIntentVerifierTarget2", + manifest: "AndroidManifest2.xml", +} + +android_test_helper_app { + name: "PackageManagerTestIntentVerifierTarget3", + manifest: "AndroidManifest3.xml", +} + +android_test_helper_app { + name: "PackageManagerTestIntentVerifierTarget4Base", + manifest: "AndroidManifest4Base.xml", +} + +android_test_helper_app { + name: "PackageManagerTestIntentVerifierTarget4NoAutoVerify", + manifest: "AndroidManifest4NoAutoVerify.xml", +} + +android_test_helper_app { + name: "PackageManagerTestIntentVerifierTarget4Wildcard", + manifest: "AndroidManifest4Wildcard.xml", +} + +android_test_helper_app { + name: "PackageManagerTestIntentVerifierTarget4WildcardNoAutoVerify", + manifest: "AndroidManifest4WildcardNoAutoVerify.xml", +} diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest1.xml b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest1.xml new file mode 100644 index 000000000000..6cf5c7619a30 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest1.xml @@ -0,0 +1,94 @@ +<?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. + --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.server.pm.test.intent.verifier.target.one" android:versionCode="1"> + + <application> + <activity android:name=".TargetActivity" android:exported="true"> + <intent-filter android:autoVerify="true"> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="http" /> + <data android:scheme="https" /> + <data android:host="verify.pm.server.android.com" /> + </intent-filter> + + <intent-filter android:autoVerify="false"> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="http" /> + <data android:scheme="https" /> + <data android:host="no_verify.pm.server.android.com" /> + </intent-filter> + + <intent-filter android:autoVerify="true"> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="http" /> + <data android:host="http_only.pm.server.android.com" /> + </intent-filter> + + <intent-filter android:autoVerify="true"> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="https" /> + <data android:host="https_only.pm.server.android.com" /> + </intent-filter> + + <intent-filter android:autoVerify="true"> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="htttps" /> + <data android:host="non_http.pm.server.android.com" /> + </intent-filter> + + <intent-filter android:autoVerify="true"> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="https" /> + <data android:scheme="non_web_scheme" /> + <data android:host="https_plus_non_web_scheme.pm.server.android.com" /> + </intent-filter> + </activity> + + <activity android:name=".TargetActivity2" android:exported="true"> + <intent-filter android:autoVerify="true"> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="http" /> + <data android:scheme="https" /> + <data android:host="other_activity.pm.server.android.com" /> + </intent-filter> + + <intent-filter android:autoVerify="true"> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="http" /> + <data android:scheme="https" /> + <data android:host="multiple.pm.server.android.com" /> + </intent-filter> + </activity> + </application> + +</manifest> diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest2.xml b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest2.xml new file mode 100644 index 000000000000..087ef70595f9 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest2.xml @@ -0,0 +1,34 @@ +<?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. + --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.server.pm.test.intent.verifier.target.two" + android:versionCode="1"> + + <application> + <activity android:name=".TargetActivity" android:exported="true"> + <intent-filter android:autoVerify="true"> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="http" /> + <data android:scheme="https" /> + <data android:scheme="non_web_scheme" /> + <data android:host="only_https_plus_non_web_scheme.pm.server.android.com" /> + </intent-filter> + </activity> + </application> + +</manifest> diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest3.xml b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest3.xml new file mode 100644 index 000000000000..eb75b5e53bc8 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest3.xml @@ -0,0 +1,32 @@ +<?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. + --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.server.pm.test.intent.verifier.target.three" + android:versionCode="1"> + + <application> + <activity android:name=".TargetActivity" android:exported="true"> + <intent-filter android:autoVerify="true"> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="http" /> + <data android:host="multiple.pm.server.android.com" /> + </intent-filter> + </activity> + </application> + +</manifest> diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest4Base.xml b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest4Base.xml new file mode 100644 index 000000000000..7eacb8bc8fb7 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest4Base.xml @@ -0,0 +1,33 @@ +<?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. + --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.server.pm.test.intent.verifier.target.four" + android:versionCode="1"> + + <application> + <activity android:name=".TargetActivity" android:exported="true"> + <intent-filter android:autoVerify="true"> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="http" /> + <data android:scheme="https" /> + <data android:host="failing.pm.server.android.com" /> + </intent-filter> + </activity> + </application> + +</manifest> diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest4NoAutoVerify.xml b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest4NoAutoVerify.xml new file mode 100644 index 000000000000..ecfee55b9c4a --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest4NoAutoVerify.xml @@ -0,0 +1,33 @@ +<?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. + --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.server.pm.test.intent.verifier.target.four" + android:versionCode="1"> + + <application> + <activity android:name=".TargetActivity" android:exported="true"> + <intent-filter android:autoVerify="false"> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="http" /> + <data android:scheme="https" /> + <data android:host="failing.pm.server.android.com" /> + </intent-filter> + </activity> + </application> + +</manifest> diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest4Wildcard.xml b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest4Wildcard.xml new file mode 100644 index 000000000000..0f0f53ba07e9 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest4Wildcard.xml @@ -0,0 +1,34 @@ +<?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. + --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.server.pm.test.intent.verifier.target.four" + android:versionCode="1"> + + <application> + <activity android:name=".TargetActivity" android:exported="true"> + <intent-filter android:autoVerify="true"> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="http" /> + <data android:scheme="https" /> + <data android:host="failing.pm.server.android.com" /> + <data android:host="*.wildcard.tld" /> + </intent-filter> + </activity> + </application> + +</manifest> diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest4WildcardNoAutoVerify.xml b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest4WildcardNoAutoVerify.xml new file mode 100644 index 000000000000..d5652e1b924d --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/AndroidManifest4WildcardNoAutoVerify.xml @@ -0,0 +1,34 @@ +<?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. + --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.server.pm.test.intent.verifier.target.four" + android:versionCode="1"> + + <application> + <activity android:name=".TargetActivity" android:exported="true"> + <intent-filter android:autoVerify="false"> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="http" /> + <data android:scheme="https" /> + <data android:host="failing.pm.server.android.com" /> + <data android:host="*.wildcard.tld" /> + </intent-filter> + </activity> + </application> + +</manifest> diff --git a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java index 2f5e8839504b..3220dff553d3 100644 --- a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java @@ -48,6 +48,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.net.Uri; import android.os.BatteryManager; import android.os.Handler; import android.os.Looper; @@ -282,7 +283,7 @@ public class AppStateTrackerTest { eq(ServiceType.FORCE_ALL_APPS_STANDBY), powerSaveObserverCaptor.capture()); - verify(mMockContext).registerReceiver( + verify(mMockContext, times(2)).registerReceiver( receiverCaptor.capture(), any(IntentFilter.class)); verify(mMockAppStandbyInternal).addListener( appIdleStateChangeListenerCaptor.capture()); @@ -1242,6 +1243,67 @@ public class AppStateTrackerTest { assertTrue(instance.isForceAllAppsStandbyEnabled()); } + @Test + public void testStateClearedOnPackageRemoved() throws Exception { + final AppStateTrackerTestable instance = newInstance(); + callStart(instance); + + instance.mActiveUids.put(UID_1, true); + instance.mForegroundUids.put(UID_2, true); + instance.mRunAnyRestrictedPackages.add(Pair.create(UID_1, PACKAGE_1)); + instance.mExemptedBucketPackages.add(UserHandle.getUserId(UID_2), PACKAGE_2); + + // Replace PACKAGE_1, nothing should change + Intent packageRemoved = new Intent(Intent.ACTION_PACKAGE_REMOVED) + .putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(UID_1)) + .putExtra(Intent.EXTRA_UID, UID_1) + .putExtra(Intent.EXTRA_REPLACING, true) + .setData(Uri.fromParts(IntentFilter.SCHEME_PACKAGE, PACKAGE_1, null)); + mReceiver.onReceive(mMockContext, packageRemoved); + + assertEquals(1, instance.mActiveUids.size()); + assertEquals(1, instance.mForegroundUids.size()); + assertEquals(1, instance.mRunAnyRestrictedPackages.size()); + assertEquals(1, instance.mExemptedBucketPackages.size()); + + // Replace PACKAGE_2, nothing should change + packageRemoved = new Intent(Intent.ACTION_PACKAGE_REMOVED) + .putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(UID_2)) + .putExtra(Intent.EXTRA_UID, UID_2) + .putExtra(Intent.EXTRA_REPLACING, true) + .setData(Uri.fromParts(IntentFilter.SCHEME_PACKAGE, PACKAGE_2, null)); + mReceiver.onReceive(mMockContext, packageRemoved); + + assertEquals(1, instance.mActiveUids.size()); + assertEquals(1, instance.mForegroundUids.size()); + assertEquals(1, instance.mRunAnyRestrictedPackages.size()); + assertEquals(1, instance.mExemptedBucketPackages.size()); + + // Remove PACKAGE_1 + packageRemoved = new Intent(Intent.ACTION_PACKAGE_REMOVED) + .putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(UID_1)) + .putExtra(Intent.EXTRA_UID, UID_1) + .setData(Uri.fromParts(IntentFilter.SCHEME_PACKAGE, PACKAGE_1, null)); + mReceiver.onReceive(mMockContext, packageRemoved); + + assertEquals(0, instance.mActiveUids.size()); + assertEquals(1, instance.mForegroundUids.size()); + assertEquals(0, instance.mRunAnyRestrictedPackages.size()); + assertEquals(1, instance.mExemptedBucketPackages.size()); + + // Remove PACKAGE_2 + packageRemoved = new Intent(Intent.ACTION_PACKAGE_REMOVED) + .putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(UID_2)) + .putExtra(Intent.EXTRA_UID, UID_2) + .setData(Uri.fromParts(IntentFilter.SCHEME_PACKAGE, PACKAGE_2, null)); + mReceiver.onReceive(mMockContext, packageRemoved); + + assertEquals(0, instance.mActiveUids.size()); + assertEquals(0, instance.mForegroundUids.size()); + assertEquals(0, instance.mRunAnyRestrictedPackages.size()); + assertEquals(0, instance.mExemptedBucketPackages.size()); + } + static int[] array(int... appIds) { Arrays.sort(appIds); return appIds; diff --git a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java index 02d10e3b6ce1..b7a36f2eaed2 100644 --- a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java @@ -223,9 +223,24 @@ public class VibratorServiceTest { } @Test - public void arePrimitivesSupported_withComposeCapability_returnsAlwaysTrue() { + public void arePrimitivesSupported_withNullResultFromNative_returnsAlwaysFalse() { mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); - assertArrayEquals(new boolean[]{true, true}, + when(mNativeWrapperMock.vibratorGetSupportedPrimitives()).thenReturn(null); + + assertArrayEquals(new boolean[]{false, false}, + createService().arePrimitivesSupported(new int[]{ + VibrationEffect.Composition.PRIMITIVE_CLICK, + VibrationEffect.Composition.PRIMITIVE_QUICK_RISE + })); + } + + @Test + public void arePrimitivesSupported_withSomeSupportedPrimitives_returnsBasedOnNativeResult() { + mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); + when(mNativeWrapperMock.vibratorGetSupportedPrimitives()) + .thenReturn(new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}); + + assertArrayEquals(new boolean[]{true, false}, createService().arePrimitivesSupported(new int[]{ VibrationEffect.Composition.PRIMITIVE_CLICK, VibrationEffect.Composition.PRIMITIVE_QUICK_RISE diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java index a5df53205a36..94cad1ed18b8 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java @@ -269,21 +269,6 @@ public class AuthServiceTest { eq(callback), eq(UserHandle.getCallingUserId())); } - @Test - public void testResetLockout_callsBiometricServiceResetLockout() throws - Exception { - mAuthService = new AuthService(mContext, mInjector); - mAuthService.onStart(); - - final int userId = 100; - final byte[] token = new byte[0]; - - mAuthService.mImpl.resetLockout(userId, token); - - waitForIdle(); - verify(mBiometricService).resetLockout(eq(userId), AdditionalMatchers.aryEq(token)); - } - private static void waitForIdle() { InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java index dad360d40515..36c55cce076b 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java @@ -17,7 +17,6 @@ package com.android.server.biometrics.sensors; import android.content.Context; -import android.os.IBinder; import android.platform.test.annotations.Presubmit; import androidx.annotation.NonNull; @@ -56,8 +55,8 @@ public class BiometricSchedulerTest { mScheduler.scheduleClientMonitor(client1); mScheduler.scheduleClientMonitor(client2); - client1.mFinishCallback.onClientFinished(client1, true /* success */); - client1.mFinishCallback.onClientFinished(client1, true /* success */); + client1.mCallback.onClientFinished(client1, true /* success */); + client1.mCallback.onClientFinished(client1, true /* success */); } private static class TestClientMonitor extends ClientMonitor<Object> { diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index 8fc228734f37..32afe8244eb6 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -149,6 +149,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { public static final String NOT_PROFILE_OWNER_MSG = "does not own the profile"; public static final String NOT_ORG_OWNED_PROFILE_OWNER_MSG = "not the profile owner on organization-owned device"; + public static final String INVALID_CALLING_IDENTITY_MSG = "Calling identity is not authorized"; public static final String ONGOING_CALL_MSG = "ongoing call on the device"; // TODO replace all instances of this with explicit {@link #mServiceContext}. @@ -2404,13 +2405,13 @@ public class DevicePolicyManagerTest extends DpmTestBase { // Set admin1 as DA. dpm.setActiveAdmin(admin1, false); assertTrue(dpm.isAdminActive(admin1)); - assertExpectException(SecurityException.class, /* messageRegex= */ NOT_DEVICE_OWNER_MSG, - () -> dpm.reboot(admin1)); + assertExpectException(SecurityException.class, /* messageRegex= */ + INVALID_CALLING_IDENTITY_MSG, () -> dpm.reboot(admin1)); // Set admin1 as PO. assertTrue(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM)); - assertExpectException(SecurityException.class, /* messageRegex= */ NOT_DEVICE_OWNER_MSG, - () -> dpm.reboot(admin1)); + assertExpectException(SecurityException.class, /* messageRegex= */ + INVALID_CALLING_IDENTITY_MSG, () -> dpm.reboot(admin1)); // Remove PO and add DO. dpm.clearProfileOwner(admin1); @@ -2623,7 +2624,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { UserHandle.myUserId(), UserManager.RESTRICTION_SOURCE_DEVICE_OWNER)) ).when(getServices().userManager).getUserRestrictionSources( eq(UserManager.DISALLOW_ADJUST_VOLUME), - eq(UserHandle.getUserHandleForUid(UserHandle.myUserId()))); + eq(UserHandle.of(UserHandle.myUserId()))); intent = dpm.createAdminSupportIntent(UserManager.DISALLOW_ADJUST_VOLUME); assertNotNull(intent); assertEquals(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS, intent.getAction()); diff --git a/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java index f9343236662b..7b07102356f0 100644 --- a/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java @@ -74,7 +74,7 @@ public class TunerResourceManagerServiceTest { mReclaimed = true; } - public boolean isRelaimed() { + public boolean isReclaimed() { return mReclaimed; } } @@ -387,13 +387,13 @@ public class TunerResourceManagerServiceTest { new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBT); assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isFalse(); - assertThat(listener.isRelaimed()).isFalse(); + assertThat(listener.isReclaimed()).isFalse(); request = new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBS); assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isFalse(); - assertThat(listener.isRelaimed()).isFalse(); + assertThat(listener.isReclaimed()).isFalse(); } @Test @@ -452,7 +452,7 @@ public class TunerResourceManagerServiceTest { .getOwnerClientId()).isEqualTo(clientId1[0]); assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) .getOwnerClientId()).isEqualTo(clientId1[0]); - assertThat(listener.isRelaimed()).isTrue(); + assertThat(listener.isReclaimed()).isTrue(); } @Test @@ -486,7 +486,7 @@ public class TunerResourceManagerServiceTest { // Release frontend mTunerResourceManagerService.releaseFrontendInternal(mTunerResourceManagerService - .getFrontendResource(frontendId)); + .getFrontendResource(frontendId), clientId[0]); assertThat(mTunerResourceManagerService .getFrontendResource(frontendId).isInUse()).isFalse(); assertThat(mTunerResourceManagerService @@ -548,7 +548,7 @@ public class TunerResourceManagerServiceTest { assertThat(mTunerResourceManagerService.getCasResource(1) .getOwnerClientIds()).isEqualTo(new HashSet<Integer>(Arrays.asList(clientId1[0]))); assertThat(mTunerResourceManagerService.getCasResource(1).isFullyUsed()).isFalse(); - assertThat(listener.isRelaimed()).isTrue(); + assertThat(listener.isReclaimed()).isTrue(); } @Test @@ -633,7 +633,7 @@ public class TunerResourceManagerServiceTest { .isInUse()).isTrue(); assertThat(mTunerResourceManagerService.getLnbResource(lnbIds[0]) .getOwnerClientId()).isEqualTo(clientId1[0]); - assertThat(listener.isRelaimed()).isTrue(); + assertThat(listener.isReclaimed()).isTrue(); assertThat(mTunerResourceManagerService.getClientProfile(clientId0[0]) .getInUseLnbIds().size()).isEqualTo(0); } @@ -761,4 +761,293 @@ public class TunerResourceManagerServiceTest { backgroundRecordProfile)).isEqualTo( (backgroundPlaybackPriority > backgroundRecordPriority)); } + + @Test + public void shareFrontendTest_FrontendWithExclusiveGroupReadyToShare() { + /**** Register Clients and Set Priority ****/ + + // Int array to save the returned client ids + int[] ownerClientId0 = new int[1]; + int[] ownerClientId1 = new int[1]; + int[] shareClientId0 = new int[1]; + int[] shareClientId1 = new int[1]; + + // Predefined client profiles + ResourceClientProfile[] ownerProfiles = new ResourceClientProfile[2]; + ResourceClientProfile[] shareProfiles = new ResourceClientProfile[2]; + ownerProfiles[0] = new ResourceClientProfile( + "0" /*sessionId*/, + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_LIVE); + ownerProfiles[1] = new ResourceClientProfile( + "1" /*sessionId*/, + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_LIVE); + shareProfiles[0] = new ResourceClientProfile( + "2" /*sessionId*/, + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD); + shareProfiles[1] = new ResourceClientProfile( + "3" /*sessionId*/, + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD); + + // Predefined client reclaim listeners + TestResourcesReclaimListener ownerListener0 = new TestResourcesReclaimListener(); + TestResourcesReclaimListener shareListener0 = new TestResourcesReclaimListener(); + TestResourcesReclaimListener ownerListener1 = new TestResourcesReclaimListener(); + TestResourcesReclaimListener shareListener1 = new TestResourcesReclaimListener(); + // Register clients and validate the returned client ids + mTunerResourceManagerService + .registerClientProfileInternal(ownerProfiles[0], ownerListener0, ownerClientId0); + mTunerResourceManagerService + .registerClientProfileInternal(shareProfiles[0], shareListener0, shareClientId0); + mTunerResourceManagerService + .registerClientProfileInternal(ownerProfiles[1], ownerListener1, ownerClientId1); + mTunerResourceManagerService + .registerClientProfileInternal(shareProfiles[1], shareListener1, shareClientId1); + assertThat(ownerClientId0[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); + assertThat(shareClientId0[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); + assertThat(ownerClientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); + assertThat(shareClientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); + + mTunerResourceManagerService.updateClientPriorityInternal( + ownerClientId0[0], + 100/*priority*/, + 0/*niceValue*/); + mTunerResourceManagerService.updateClientPriorityInternal( + shareClientId0[0], + 200/*priority*/, + 0/*niceValue*/); + mTunerResourceManagerService.updateClientPriorityInternal( + ownerClientId1[0], + 300/*priority*/, + 0/*niceValue*/); + mTunerResourceManagerService.updateClientPriorityInternal( + shareClientId1[0], + 400/*priority*/, + 0/*niceValue*/); + + /**** Init Frontend Resources ****/ + + // Predefined frontend info + TunerFrontendInfo[] infos = new TunerFrontendInfo[2]; + infos[0] = new TunerFrontendInfo( + 0 /*id*/, + FrontendSettings.TYPE_DVBT, + 1 /*exclusiveGroupId*/); + infos[1] = new TunerFrontendInfo( + 1 /*id*/, + FrontendSettings.TYPE_DVBS, + 1 /*exclusiveGroupId*/); + + /**** Init Lnb Resources ****/ + int[] lnbIds = {1}; + mTunerResourceManagerService.setLnbInfoListInternal(lnbIds); + + // Update frontend list in TRM + mTunerResourceManagerService.setFrontendInfoListInternal(infos); + + /**** Request Frontend ****/ + + // Predefined frontend request and array to save returned frontend handle + int[] frontendHandle = new int[1]; + TunerFrontendRequest request = new TunerFrontendRequest( + ownerClientId0[0] /*clientId*/, + FrontendSettings.TYPE_DVBT); + + // Request call and validate granted resource and internal mapping + assertThat(mTunerResourceManagerService + .requestFrontendInternal(request, frontendHandle)) + .isTrue(); + assertThat(mTunerResourceManagerService + .getResourceIdFromHandle(frontendHandle[0])) + .isEqualTo(infos[0].getId()); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId0[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + + /**** Share Frontend ****/ + + // Share frontend call and validate the internal mapping + mTunerResourceManagerService.shareFrontendInternal( + shareClientId0[0]/*selfClientId*/, + ownerClientId0[0]/*targetClientId*/); + mTunerResourceManagerService.shareFrontendInternal( + shareClientId1[0]/*selfClientId*/, + ownerClientId0[0]/*targetClientId*/); + // Verify fe in use status + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) + .isInUse()).isTrue(); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) + .isInUse()).isTrue(); + // Verify fe owner status + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) + .getOwnerClientId()).isEqualTo(ownerClientId0[0]); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) + .getOwnerClientId()).isEqualTo(ownerClientId0[0]); + // Verify share fe client status in the primary owner client + assertThat(mTunerResourceManagerService.getClientProfile(ownerClientId0[0]) + .getShareFeClientIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + shareClientId0[0], + shareClientId1[0]))); + // Verify in use frontend list in all the primary owner and share owner clients + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId0[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId1[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + + /**** Remove Frontend Share Owner ****/ + + // Unregister the second share fe client + mTunerResourceManagerService.unregisterClientProfileInternal(shareClientId1[0]); + + // Validate the internal mapping + assertThat(mTunerResourceManagerService.getClientProfile(ownerClientId0[0]) + .getShareFeClientIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + shareClientId0[0]))); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId0[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + + /**** Request Shared Frontend with Higher Priority Client ****/ + + // Predefined second frontend request + request = new TunerFrontendRequest( + ownerClientId1[0] /*clientId*/, + FrontendSettings.TYPE_DVBT); + + // Second request call + assertThat(mTunerResourceManagerService + .requestFrontendInternal(request, frontendHandle)) + .isTrue(); + + // Validate granted resource and internal mapping + assertThat(mTunerResourceManagerService + .getResourceIdFromHandle(frontendHandle[0])) + .isEqualTo(infos[0].getId()); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) + .getOwnerClientId()).isEqualTo(ownerClientId1[0]); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) + .getOwnerClientId()).isEqualTo(ownerClientId1[0]); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId1[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId0[0]) + .getInUseFrontendIds() + .isEmpty()) + .isTrue(); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseFrontendIds() + .isEmpty()) + .isTrue(); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId0[0]) + .getShareFeClientIds() + .isEmpty()) + .isTrue(); + assertThat(ownerListener0.isReclaimed()).isTrue(); + assertThat(shareListener0.isReclaimed()).isTrue(); + + /**** Release Frontend Resource From Primary Owner ****/ + + // Reshare the frontend + mTunerResourceManagerService.shareFrontendInternal( + shareClientId0[0]/*selfClientId*/, + ownerClientId1[0]/*targetClientId*/); + + // Release the frontend resource from the primary owner + mTunerResourceManagerService.releaseFrontendInternal(mTunerResourceManagerService + .getFrontendResource(infos[0].getId()), ownerClientId1[0]); + + // Validate the internal mapping + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) + .isInUse()).isFalse(); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) + .isInUse()).isFalse(); + // Verify client status + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId1[0]) + .getInUseFrontendIds() + .isEmpty()) + .isTrue(); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseFrontendIds() + .isEmpty()) + .isTrue(); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId1[0]) + .getShareFeClientIds() + .isEmpty()) + .isTrue(); + + /**** Unregister Primary Owner when the Share owner owns an Lnb ****/ + + // Predefined Lnb request and handle array + TunerLnbRequest requestLnb = new TunerLnbRequest(shareClientId0[0]); + int[] lnbHandle = new int[1]; + + // Request for an Lnb + assertThat(mTunerResourceManagerService + .requestLnbInternal(requestLnb, lnbHandle)) + .isTrue(); + + // Request and share the frontend resource again + assertThat(mTunerResourceManagerService + .requestFrontendInternal(request, frontendHandle)) + .isTrue(); + mTunerResourceManagerService.shareFrontendInternal( + shareClientId0[0]/*selfClientId*/, + ownerClientId1[0]/*targetClientId*/); + + // Unregister the primary owner of the shared frontend + mTunerResourceManagerService.unregisterClientProfileInternal(ownerClientId1[0]); + + // Validate the internal mapping + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) + .isInUse()).isFalse(); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) + .isInUse()).isFalse(); + // Verify client status + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseFrontendIds() + .isEmpty()) + .isTrue(); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseLnbIds()) + .isEqualTo(new HashSet<Integer>(Arrays.asList( + lnbIds[0]))); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java index 46c3e22da38c..eb78172cd562 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java @@ -20,6 +20,7 @@ import static android.app.ActivityManager.START_SUCCESS; import static android.app.ActivityManager.START_TASK_TO_FRONT; import static android.content.ComponentName.createRelative; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions; @@ -176,7 +177,8 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { public void testOnActivityLaunchCancelled_hasDrawn() { onActivityLaunched(mTopActivity); - mTopActivity.mVisibleRequested = mTopActivity.mDrawn = true; + mTopActivity.mVisibleRequested = true; + doReturn(true).when(mTopActivity).isReportedDrawn(); // Cannot time already-visible activities. notifyActivityLaunched(START_TASK_TO_FRONT, mTopActivity); @@ -187,16 +189,14 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { @Test public void testOnActivityLaunchCancelled_finishedBeforeDrawn() { - mTopActivity.mVisibleRequested = mTopActivity.mDrawn = true; + mTopActivity.mVisibleRequested = true; + doReturn(true).when(mTopActivity).isReportedDrawn(); - // Suppress resume when creating the record because we want to notify logger manually. - mSupervisor.beginDeferResume(); // Create an activity with different process that meets process switch. final ActivityRecord noDrawnActivity = new ActivityBuilder(mAtm) .setTask(mTopActivity.getTask()) .setProcessName("other") .build(); - mSupervisor.readyToResume(); notifyActivityLaunching(noDrawnActivity.intent); notifyActivityLaunched(START_SUCCESS, noDrawnActivity); @@ -294,7 +294,7 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { public void testOnActivityLaunchCancelledTrampoline() { onActivityLaunchedTrampoline(); - mTopActivity.mDrawn = true; + doReturn(true).when(mTopActivity).isReportedDrawn(); // Cannot time already-visible activities. notifyActivityLaunched(START_TASK_TO_FRONT, mTopActivity); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java index 1e95aba0c2d7..27e2d1370fae 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java @@ -22,6 +22,7 @@ import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; @@ -38,13 +39,8 @@ import static org.mockito.ArgumentMatchers.eq; import android.app.WaitResult; import android.content.pm.ActivityInfo; -import android.graphics.PixelFormat; -import android.hardware.display.DisplayManager; -import android.hardware.display.VirtualDisplay; -import android.media.ImageReader; import android.platform.test.annotations.Presubmit; import android.view.Display; -import android.view.DisplayInfo; import androidx.test.filters.MediumTest; @@ -180,53 +176,28 @@ public class ActivityStackSupervisorTests extends WindowTestsBase { eq(true) /* focused */); } + /** + * Ensures that a trusted display can launch arbitrary activity and an untrusted display can't. + */ @Test - /** Ensures that a trusted virtual display can launch arbitrary activities. */ - public void testTrustedVirtualDisplayCanLaunchActivities() { - final DisplayContent newDisplay = addNewDisplayContentAt(DisplayContent.POSITION_TOP); - final Task stack = new StackBuilder(mRootWindowContainer) - .setDisplay(newDisplay).build(); - final ActivityRecord unresizableActivity = stack.getTopNonFinishingActivity(); - VirtualDisplay virtualDisplay = createVirtualDisplay(true); - final boolean allowed = mSupervisor.isCallerAllowedToLaunchOnDisplay(1234, 1234, - virtualDisplay.getDisplay().getDisplayId(), unresizableActivity.info); + public void testDisplayCanLaunchActivities() { + final Display display = mDisplayContent.mDisplay; + // An empty info without FLAG_ALLOW_EMBEDDED. + final ActivityInfo activityInfo = new ActivityInfo(); + final int callingPid = 12345; + final int callingUid = 12345; + spyOn(display); - assertThat(allowed).isTrue(); + doReturn(true).when(display).isTrusted(); + final boolean allowedOnTrusted = mSupervisor.isCallerAllowedToLaunchOnDisplay(callingPid, + callingUid, display.getDisplayId(), activityInfo); - virtualDisplay.release(); - } + assertThat(allowedOnTrusted).isTrue(); - @Test - /** Ensures that an untrusted virtual display cannot launch arbitrary activities. */ - public void testUntrustedVirtualDisplayCannotLaunchActivities() { - final DisplayContent newDisplay = addNewDisplayContentAt(DisplayContent.POSITION_TOP); - final Task stack = new StackBuilder(mRootWindowContainer) - .setDisplay(newDisplay).build(); - final ActivityRecord unresizableActivity = stack.getTopNonFinishingActivity(); - VirtualDisplay virtualDisplay = createVirtualDisplay(false); - final boolean allowed = mSupervisor.isCallerAllowedToLaunchOnDisplay(1234, 1234, - virtualDisplay.getDisplay().getDisplayId(), unresizableActivity.info); - - assertThat(allowed).isFalse(); - - virtualDisplay.release(); - } + doReturn(false).when(display).isTrusted(); + final boolean allowedOnUntrusted = mSupervisor.isCallerAllowedToLaunchOnDisplay(callingPid, + callingUid, display.getDisplayId(), activityInfo); - private VirtualDisplay createVirtualDisplay(boolean trusted) { - final DisplayManager dm = mContext.getSystemService(DisplayManager.class); - final DisplayInfo displayInfo = new DisplayInfo(); - final Display defaultDisplay = dm.getDisplay(Display.DEFAULT_DISPLAY); - defaultDisplay.getDisplayInfo(displayInfo); - int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC; - if (trusted) { - flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; - } - - final ImageReader imageReader = ImageReader.newInstance( - displayInfo.logicalWidth, displayInfo.logicalHeight, PixelFormat.RGBA_8888, 2); - - return dm.createVirtualDisplay("virtualDisplay", displayInfo.logicalWidth, - displayInfo.logicalHeight, - displayInfo.logicalDensityDpi, imageReader.getSurface(), flags); + assertThat(allowedOnUntrusted).isFalse(); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java index 1ec9bd24ad59..b89d16807a6e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java @@ -890,8 +890,8 @@ public class RootActivityContainerTests extends WindowTestsBase { // Make sure the root task is valid and can be reused on default display. final Task stack = mRootWindowContainer.getValidLaunchStackInTaskDisplayArea( - mRootWindowContainer.getDefaultTaskDisplayArea(), activity, task, null, - null); + mRootWindowContainer.getDefaultTaskDisplayArea(), activity, task, + null /* options */, null /* launchParams */); assertEquals(task, stack); } diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 78556ef41edb..1e5d92b270d2 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -61,7 +61,6 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ParceledListSlice; import android.content.pm.ShortcutServiceInternal; -import android.content.pm.UserInfo; import android.content.res.Configuration; import android.os.Binder; import android.os.Environment; @@ -306,25 +305,25 @@ public class UsageStatsService extends SystemService implements @Override public void onUserStopping(@NonNull TargetUser user) { - final UserInfo userInfo = user.getUserInfo(); + final int userId = user.getUserIdentifier(); synchronized (mLock) { // User was started but never unlocked so no need to report a user stopped event - if (!mUserUnlockedStates.get(userInfo.id)) { - persistPendingEventsLocked(userInfo.id); + if (!mUserUnlockedStates.get(userId)) { + persistPendingEventsLocked(userId); return; } // Report a user stopped event before persisting all stats to disk via the user service final Event event = new Event(USER_STOPPED, SystemClock.elapsedRealtime()); event.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME; - reportEvent(event, userInfo.id); - final UserUsageStatsService userService = mUserState.get(userInfo.id); + reportEvent(event, userId); + final UserUsageStatsService userService = mUserState.get(userId); if (userService != null) { userService.userStopped(); } - mUserUnlockedStates.put(userInfo.id, false); - mUserState.put(userInfo.id, null); // release the service (mainly for GC) + mUserUnlockedStates.put(userId, false); + mUserState.put(userId, null); // release the service (mainly for GC) } } diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java index 0ea84da54b60..26d46dbd2ab7 100644 --- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java +++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java @@ -1276,7 +1276,8 @@ public class SoundTriggerService extends SystemService { * @return The initialized AudioRecord */ private @NonNull AudioRecord createAudioRecordForEvent( - @NonNull SoundTrigger.GenericRecognitionEvent event) { + @NonNull SoundTrigger.GenericRecognitionEvent event) + throws IllegalArgumentException, UnsupportedOperationException { AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder(); attributesBuilder.setInternalCapturePreset(MediaRecorder.AudioSource.HOTWORD); AudioAttributes attributes = attributesBuilder.build(); @@ -1285,21 +1286,15 @@ public class SoundTriggerService extends SystemService { sEventLogger.log(new SoundTriggerLogger.StringEvent("createAudioRecordForEvent")); - try { - return (new AudioRecord.Builder()) - .setAudioAttributes(attributes) - .setAudioFormat((new AudioFormat.Builder()) - .setChannelMask(originalFormat.getChannelMask()) - .setEncoding(originalFormat.getEncoding()) - .setSampleRate(originalFormat.getSampleRate()) - .build()) - .setSessionId(event.getCaptureSession()) - .build(); - } catch (IllegalArgumentException | UnsupportedOperationException e) { - Slog.w(TAG, mPuuid + ": createAudioRecordForEvent(" + event - + "), failed to create AudioRecord"); - return null; - } + return (new AudioRecord.Builder()) + .setAudioAttributes(attributes) + .setAudioFormat((new AudioFormat.Builder()) + .setChannelMask(originalFormat.getChannelMask()) + .setEncoding(originalFormat.getEncoding()) + .setSampleRate(originalFormat.getSampleRate()) + .build()) + .setSessionId(event.getCaptureSession()) + .build(); } @Override @@ -1325,13 +1320,13 @@ public class SoundTriggerService extends SystemService { // execute if throttled: () -> { if (event.isCaptureAvailable()) { - AudioRecord capturedData = createAudioRecordForEvent(event); - - // Currently we need to start and release the audio record to reset - // the DSP even if we don't want to process the event - if (capturedData != null) { + try { + AudioRecord capturedData = createAudioRecordForEvent(event); capturedData.startRecording(); capturedData.release(); + } catch (IllegalArgumentException | UnsupportedOperationException e) { + Slog.w(TAG, mPuuid + ": createAudioRecordForEvent(" + event + + "), failed to create AudioRecord"); } } })); diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index 9ff44eba8fa0..a2215ceed36a 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -164,13 +164,13 @@ public class VoiceInteractionManagerService extends SystemService { } } - private boolean isSupported(UserInfo user) { + @Override + public boolean isUserSupported(@NonNull TargetUser user) { return user.isFull(); } - @Override - public boolean isUserSupported(TargetUser user) { - return isSupported(user.getUserInfo()); + private boolean isUserSupported(@NonNull UserInfo user) { + return user.isFull(); } @Override @@ -461,7 +461,7 @@ public class VoiceInteractionManagerService extends SystemService { private void setCurrentUserLocked(@UserIdInt int userHandle) { mCurUser = userHandle; final UserInfo userInfo = mUserManagerInternal.getUserInfo(mCurUser); - mCurUserSupported = isSupported(userInfo); + mCurUserSupported = isUserSupported(userInfo); } public void switchUser(@UserIdInt int userHandle) { diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java index e34bbfcde492..06c34dcf290a 100644 --- a/telephony/java/android/telephony/CellIdentityNr.java +++ b/telephony/java/android/telephony/CellIdentityNr.java @@ -37,7 +37,7 @@ public final class CellIdentityNr extends CellIdentity { private static final String TAG = "CellIdentityNr"; private static final int MAX_PCI = 1007; - private static final int MAX_TAC = 65535; + private static final int MAX_TAC = 16777215; // 0xffffff private static final int MAX_NRARFCN = 3279165; private static final long MAX_NCI = 68719476735L; @@ -53,7 +53,7 @@ public final class CellIdentityNr extends CellIdentity { /** * * @param pci Physical Cell Id in range [0, 1007]. - * @param tac 16-bit Tracking Area Code. + * @param tac 24-bit Tracking Area Code. * @param nrArfcn NR Absolute Radio Frequency Channel Number, in range [0, 3279165]. * @param bands Bands used by the cell. Band number defined in 3GPP TS 38.101-1 and TS 38.101-2. * @param mccStr 3-digit Mobile Country Code in string format. @@ -199,9 +199,9 @@ public final class CellIdentityNr extends CellIdentity { /** * Get the tracking area code. - * @return a 16 bit integer or {@link CellInfo#UNAVAILABLE} if unknown. + * @return a 24 bit integer or {@link CellInfo#UNAVAILABLE} if unknown. */ - @IntRange(from = 0, to = 65535) + @IntRange(from = 0, to = 16777215) public int getTac() { return mTac; } diff --git a/tests/AutoVerify/app1/Android.bp b/tests/AutoVerify/app1/Android.bp deleted file mode 100644 index 548519fa653b..000000000000 --- a/tests/AutoVerify/app1/Android.bp +++ /dev/null @@ -1,11 +0,0 @@ -android_app { - name: "AutoVerifyTest", - srcs: ["src/**/*.java"], - resource_dirs: ["res"], - platform_apis: true, - min_sdk_version: "26", - target_sdk_version: "26", - optimize: { - enabled: false, - }, -} diff --git a/tests/AutoVerify/app1/AndroidManifest.xml b/tests/AutoVerify/app1/AndroidManifest.xml deleted file mode 100644 index d9caad490d82..000000000000 --- a/tests/AutoVerify/app1/AndroidManifest.xml +++ /dev/null @@ -1,43 +0,0 @@ -<?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. ---> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.test.autoverify" > - - <uses-sdk android:targetSdkVersion="26" /> - - <application - android:label="@string/app_name" > - <activity - android:name=".MainActivity" - android:label="@string/app_name" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - - <intent-filter android:autoVerify="true"> - <action android:name="android.intent.action.VIEW" /> - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> - <data android:scheme="http" /> - <data android:scheme="https" /> - <data android:host="explicit.example.com" /> - </intent-filter> - </activity> - </application> -</manifest> diff --git a/tests/AutoVerify/app1/res/values/strings.xml b/tests/AutoVerify/app1/res/values/strings.xml deleted file mode 100644 index e234355041c6..000000000000 --- a/tests/AutoVerify/app1/res/values/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 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> - <!-- app icon label, do not translate --> - <string name="app_name" translatable="false">AutoVerify Test</string> -</resources> diff --git a/tests/AutoVerify/app2/Android.bp b/tests/AutoVerify/app2/Android.bp deleted file mode 100644 index 1c6c97bdf350..000000000000 --- a/tests/AutoVerify/app2/Android.bp +++ /dev/null @@ -1,11 +0,0 @@ -android_app { - name: "AutoVerifyTest2", - srcs: ["src/**/*.java"], - resource_dirs: ["res"], - platform_apis: true, - min_sdk_version: "26", - target_sdk_version: "26", - optimize: { - enabled: false, - }, -} diff --git a/tests/AutoVerify/app2/AndroidManifest.xml b/tests/AutoVerify/app2/AndroidManifest.xml deleted file mode 100644 index a00807883cfc..000000000000 --- a/tests/AutoVerify/app2/AndroidManifest.xml +++ /dev/null @@ -1,44 +0,0 @@ -<?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. ---> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.test.autoverify" > - - <uses-sdk android:targetSdkVersion="26" /> - - <application - android:label="@string/app_name" > - <activity - android:name=".MainActivity" - android:label="@string/app_name" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - - <intent-filter android:autoVerify="true"> - <action android:name="android.intent.action.VIEW" /> - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> - <data android:scheme="http" /> - <data android:scheme="https" /> - <data android:host="explicit.example.com" /> - <data android:host="*.wildcard.tld" /> - </intent-filter> - </activity> - </application> -</manifest> diff --git a/tests/AutoVerify/app2/res/values/strings.xml b/tests/AutoVerify/app2/res/values/strings.xml deleted file mode 100644 index e234355041c6..000000000000 --- a/tests/AutoVerify/app2/res/values/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 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> - <!-- app icon label, do not translate --> - <string name="app_name" translatable="false">AutoVerify Test</string> -</resources> diff --git a/tests/AutoVerify/app3/Android.bp b/tests/AutoVerify/app3/Android.bp deleted file mode 100644 index 70a2b77d1000..000000000000 --- a/tests/AutoVerify/app3/Android.bp +++ /dev/null @@ -1,11 +0,0 @@ -android_app { - name: "AutoVerifyTest3", - srcs: ["src/**/*.java"], - resource_dirs: ["res"], - platform_apis: true, - min_sdk_version: "26", - target_sdk_version: "26", - optimize: { - enabled: false, - }, -} diff --git a/tests/AutoVerify/app3/AndroidManifest.xml b/tests/AutoVerify/app3/AndroidManifest.xml deleted file mode 100644 index efaabc9a38d3..000000000000 --- a/tests/AutoVerify/app3/AndroidManifest.xml +++ /dev/null @@ -1,44 +0,0 @@ -<?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. ---> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.test.autoverify" > - - <uses-sdk android:targetSdkVersion="26" /> - - <application - android:label="@string/app_name" > - <activity - android:name=".MainActivity" - android:label="@string/app_name" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - - <!-- does not request autoVerify --> - <intent-filter> - <action android:name="android.intent.action.VIEW" /> - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> - <data android:scheme="http" /> - <data android:scheme="https" /> - <data android:host="explicit.example.com" /> - </intent-filter> - </activity> - </application> -</manifest> diff --git a/tests/AutoVerify/app3/res/values/strings.xml b/tests/AutoVerify/app3/res/values/strings.xml deleted file mode 100644 index e234355041c6..000000000000 --- a/tests/AutoVerify/app3/res/values/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 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> - <!-- app icon label, do not translate --> - <string name="app_name" translatable="false">AutoVerify Test</string> -</resources> diff --git a/tests/AutoVerify/app4/Android.bp b/tests/AutoVerify/app4/Android.bp deleted file mode 100644 index fbdae1181a7a..000000000000 --- a/tests/AutoVerify/app4/Android.bp +++ /dev/null @@ -1,11 +0,0 @@ -android_app { - name: "AutoVerifyTest4", - srcs: ["src/**/*.java"], - resource_dirs: ["res"], - platform_apis: true, - min_sdk_version: "26", - target_sdk_version: "26", - optimize: { - enabled: false, - }, -} diff --git a/tests/AutoVerify/app4/AndroidManifest.xml b/tests/AutoVerify/app4/AndroidManifest.xml deleted file mode 100644 index 1c975f8336c9..000000000000 --- a/tests/AutoVerify/app4/AndroidManifest.xml +++ /dev/null @@ -1,45 +0,0 @@ -<?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. ---> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.test.autoverify" > - - <uses-sdk android:targetSdkVersion="26" /> - - <application - android:label="@string/app_name" > - <activity - android:name=".MainActivity" - android:label="@string/app_name" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - - <!-- intentionally does not autoVerify --> - <intent-filter> - <action android:name="android.intent.action.VIEW" /> - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> - <data android:scheme="http" /> - <data android:scheme="https" /> - <data android:host="explicit.example.com" /> - <data android:host="*.wildcard.tld" /> - </intent-filter> - </activity> - </application> -</manifest> diff --git a/tests/AutoVerify/app4/res/values/strings.xml b/tests/AutoVerify/app4/res/values/strings.xml deleted file mode 100644 index e234355041c6..000000000000 --- a/tests/AutoVerify/app4/res/values/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 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> - <!-- app icon label, do not translate --> - <string name="app_name" translatable="false">AutoVerify Test</string> -</resources> diff --git a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java index 12f1750fb78c..781723985ec5 100644 --- a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java +++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java @@ -119,6 +119,18 @@ public class StagedInstallInternalTest { assertSessionReady(sessionId); } + @Test + public void testAbandonStagedSessionShouldCleanUp() throws Exception { + int id1 = Install.single(TestApp.A1).setStaged().createSession(); + InstallUtils.getPackageInstaller().abandonSession(id1); + int id2 = Install.multi(TestApp.A1).setStaged().createSession(); + InstallUtils.getPackageInstaller().abandonSession(id2); + int id3 = Install.single(TestApp.A1).setStaged().commit(); + InstallUtils.getPackageInstaller().abandonSession(id3); + int id4 = Install.multi(TestApp.A1).setStaged().commit(); + InstallUtils.getPackageInstaller().abandonSession(id4); + } + private static void assertSessionReady(int sessionId) { assertSessionState(sessionId, (session) -> assertThat(session.isStagedSessionReady()).isTrue()); diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java index 792e29d93be2..d7b07967f979 100644 --- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java +++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java @@ -41,6 +41,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.io.File; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; @RunWith(DeviceJUnit4ClassRunner.class) public class StagedInstallInternalTest extends BaseHostJUnit4Test { @@ -200,6 +203,28 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test { assertThat(sessionIds.length).isEqualTo(3); } + @Test + public void testAbandonStagedSessionShouldCleanUp() throws Exception { + List<String> before = getStagingDirectories(); + runPhase("testAbandonStagedSessionShouldCleanUp"); + List<String> after = getStagingDirectories(); + // The staging directories generated during the test should be deleted + assertThat(after).isEqualTo(before); + } + + private List<String> getStagingDirectories() { + String baseDir = "/data/app-staging"; + try { + return getDevice().getFileEntry(baseDir).getChildren(false) + .stream().filter(entry -> entry.getName().matches("session_\\d+")) + .map(entry -> entry.getName()) + .collect(Collectors.toList()); + } catch (Exception e) { + // Return an empty list if any error + return Collections.EMPTY_LIST; + } + } + private void restartSystemServer() throws Exception { // Restart the system server ProcessInfo oldPs = getDevice().getProcessByName("system_server"); diff --git a/tests/utils/hostutils/src/com/android/internal/util/test/SystemPreparer.java b/tests/utils/hostutils/src/com/android/internal/util/test/SystemPreparer.java index c2a5459ae125..f80af034fa2b 100644 --- a/tests/utils/hostutils/src/com/android/internal/util/test/SystemPreparer.java +++ b/tests/utils/hostutils/src/com/android/internal/util/test/SystemPreparer.java @@ -62,12 +62,22 @@ public class SystemPreparer extends ExternalResource { private final RebootStrategy mRebootStrategy; private final TearDownRule mTearDownRule; + // When debugging, it may be useful to run a test case without rebooting the device afterwards, + // to manually verify the device state. + private boolean mDebugSkipAfterReboot; + public SystemPreparer(TemporaryFolder hostTempFolder, DeviceProvider deviceProvider) { this(hostTempFolder, RebootStrategy.FULL, null, deviceProvider); } public SystemPreparer(TemporaryFolder hostTempFolder, RebootStrategy rebootStrategy, @Nullable TestRuleDelegate testRuleDelegate, DeviceProvider deviceProvider) { + this(hostTempFolder, rebootStrategy, testRuleDelegate, false, deviceProvider); + } + + public SystemPreparer(TemporaryFolder hostTempFolder, RebootStrategy rebootStrategy, + @Nullable TestRuleDelegate testRuleDelegate, boolean debugSkipAfterReboot, + DeviceProvider deviceProvider) { mHostTempFolder = hostTempFolder; mDeviceProvider = deviceProvider; mRebootStrategy = rebootStrategy; @@ -75,6 +85,7 @@ public class SystemPreparer extends ExternalResource { if (testRuleDelegate != null) { testRuleDelegate.setDelegate(mTearDownRule); } + mDebugSkipAfterReboot = debugSkipAfterReboot; } /** Copies a file within the host test jar to a path on device. */ @@ -172,7 +183,9 @@ public class SystemPreparer extends ExternalResource { case USERSPACE_UNTIL_ONLINE: device.rebootUserspaceUntilOnline(); break; - case START_STOP: + // TODO(b/159540015): Make this START_STOP instead of default once it's fixed. Can't + // currently be done because START_STOP is commented out. + default: device.executeShellCommand("stop"); device.executeShellCommand("start"); ITestDevice.RecoveryMode cachedRecoveryMode = device.getRecoveryMode(); @@ -228,7 +241,9 @@ public class SystemPreparer extends ExternalResource { for (final String packageName : mInstalledPackages) { device.uninstallPackage(packageName); } - reboot(); + if (!mDebugSkipAfterReboot) { + reboot(); + } } catch (DeviceNotAvailableException e) { Assert.fail(e.toString()); } @@ -355,6 +370,7 @@ public class SystemPreparer extends ExternalResource { /** * How to reboot the device. Ordered from slowest to fastest. */ + @SuppressWarnings("DanglingJavadoc") public enum RebootStrategy { /** @see ITestDevice#reboot() */ FULL, @@ -374,7 +390,15 @@ public class SystemPreparer extends ExternalResource { * * TODO(b/159540015): There's a bug with this causing unnecessary disk space usage, which * can eventually lead to an insufficient storage space error. + * + * This can be uncommented for local development, but should be left out when merging. + * It is done this way to hopefully be caught by code review, since merging this will + * break all of postsubmit. But the nearly 50% reduction in test runtime is worth having + * this option exist. + * + * @deprecated do not use this in merged code until bug is resolved */ - START_STOP +// @Deprecated +// START_STOP } } diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java index f919ea4c4797..393fe8d3ab9a 100644 --- a/wifi/java/android/net/wifi/SoftApConfiguration.java +++ b/wifi/java/android/net/wifi/SoftApConfiguration.java @@ -582,6 +582,7 @@ public final class SoftApConfiguration implements Parcelable { wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); break; case SECURITY_TYPE_WPA2_PSK: + case SECURITY_TYPE_WPA3_SAE_TRANSITION: wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK); break; default: diff --git a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java index c2d0d6d81e84..254434b81f8f 100644 --- a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java +++ b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java @@ -310,12 +310,6 @@ public class SoftApConfigurationTest { .build(); assertNull(band_6g_config.toWifiConfiguration()); - SoftApConfiguration sae_transition_config = new SoftApConfiguration.Builder() - .setPassphrase("secretsecret", - SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION) - .build(); - - assertNull(sae_transition_config.toWifiConfiguration()); } @Test @@ -358,5 +352,16 @@ public class SoftApConfigurationTest { assertThat(wifiConfig_2g5g.apBand).isEqualTo(WifiConfiguration.AP_BAND_ANY); assertThat(wifiConfig_2g5g.apChannel).isEqualTo(0); assertThat(wifiConfig_2g5g.hiddenSSID).isEqualTo(true); + + SoftApConfiguration softApConfig_sae_transition = new SoftApConfiguration.Builder() + .setPassphrase("secretsecret", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION) + .build(); + + WifiConfiguration wifiConfig_sae_transition = + softApConfig_sae_transition.toWifiConfiguration(); + assertThat(wifiConfig_sae_transition.getAuthType()) + .isEqualTo(WifiConfiguration.KeyMgmt.WPA2_PSK); + assertThat(wifiConfig_sae_transition.preSharedKey).isEqualTo("secretsecret"); } } |